diff --git a/README.md b/README.md index c7ca0d4..7dccc08 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Don't forget to include the _Spring Boot Loader_ dependency to your project: ```java scope(standalone) - .include(dependency("org.springframeworkboot:spring-boot-loader:3.3.2")); + .include(dependency("org.springframeworkboot:spring-boot-loader:3.3.3")); ``` Please check the [BootJarOperation documentation](https://rife2.github.io/bld-spring-boot/rife/bld/extension/BootJarOperation.html#method-summary) diff --git a/examples/lib/bld/bld-wrapper.properties b/examples/lib/bld/bld-wrapper.properties index 79c23a4..ac0204d 100644 --- a/examples/lib/bld/bld-wrapper.properties +++ b/examples/lib/bld/bld-wrapper.properties @@ -1,7 +1,7 @@ bld.downloadExtensionJavadoc=false bld.downloadExtensionSources=true bld.downloadLocation= -bld.extension-boot=com.uwyn.rife2:bld-spring-boot:0.9.7 +bld.extension-boot=com.uwyn.rife2:bld-spring-boot:0.9.8-SNAPSHOT bld.repositories=MAVEN_LOCAL,MAVEN_CENTRAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES bld.sourceDirectories= bld.version=2.0.1 diff --git a/src/main/java/rife/bld/extension/AbstractBootOperation.java b/src/main/java/rife/bld/extension/AbstractBootOperation.java index 6dd1581..be62db4 100644 --- a/src/main/java/rife/bld/extension/AbstractBootOperation.java +++ b/src/main/java/rife/bld/extension/AbstractBootOperation.java @@ -29,7 +29,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.text.MessageFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -89,6 +92,17 @@ public T destinationDirectory(String directory) throws IOException { return destinationDirectory(new File(directory)); } + /** + * Provides the destination directory in which the archive will be created. + * + * @param directory the destination directory + * @return this operation instance + * @throws IOException if an error occurs + */ + public T destinationDirectory(Path directory) throws IOException { + return destinationDirectory(directory.toFile()); + } + /** * Provides the file name that will be used for the archive creation. * @@ -275,9 +289,17 @@ public T infLibs(Collection jars) { * @return this operation instance */ public T infLibs(File... jars) { - infLibs_.addAll(List.of(jars)); - //noinspection unchecked - return (T) this; + return infLibs(List.of(jars)); + } + + /** + * Provides the libraries that will be stored in {@code BOOT-INF} or {@code WEB-INF}. + * + * @param jars one or more Java archive files + * @return this operation instance + */ + public T infLibs(Path... jars) { + return infLibsPaths(List.of(jars)); } /** @@ -287,9 +309,7 @@ public T infLibs(File... jars) { * @return this operation instance */ public T infLibs(String... jars) { - infLibs_.addAll(Arrays.stream(jars).map(File::new).toList()); - //noinspection unchecked - return (T) this; + return infLibsStrings(List.of(jars)); } /** @@ -301,6 +321,26 @@ public Collection infLibs() { return infLibs_; } + /** + * Provides the libraries that will be stored in {@code BOOT-INF} or {@code WEB-INF}. + * + * @param jars one or more Java archive files + * @return this operation instance + */ + public T infLibsPaths(Collection jars) { + return infLibs(jars.stream().map(Path::toFile).toList()); + } + + /** + * Provides the libraries that will be stored in {@code BOOT-INF} or {@code WEB-INF}. + * + * @param jars one or more Java archive files + * @return this operation instance + */ + public T infLibsStrings(Collection jars) { + return infLibs(jars.stream().map(File::new).toList()); + } + /** * Provides the Spring Boot loader launcher fully-qualified class name. *

@@ -367,17 +407,8 @@ public T launcherLibs(Collection jars) throws IOException { * @return this operation instance * @throws IOException if a JAR could not be found */ - @SuppressWarnings("UnusedReturnValue") public T launcherLibs(File... jars) throws IOException { - for (var j : jars) { - if (j.exists()) { - launcherLibs_.add(j); - } else { - throw new IOException("Spring Boot loader launcher library not found: " + j); - } - } - //noinspection unchecked - return (T) this; + return launcherLibs(List.of(jars)); } /** @@ -387,18 +418,41 @@ public T launcherLibs(File... jars) throws IOException { * @return this operation instance * @throws IOException if a JAR could not be found */ - @SuppressWarnings("UnusedReturnValue") public T launcherLibs(String... jars) throws IOException { - for (var j : jars) { - var p = Path.of(j); - if (Files.exists(p)) { - launcherLibs_.add(p.toFile()); - } else { - throw new IOException("Spring Boot loader launcher library not found: " + j); - } - } - //noinspection unchecked - return (T) this; + return launcherLibsStrings(List.of(jars)); + } + + /** + * Provides the libraries for the Spring Boot loader launcher. + * + * @param jars one or more Java archives + * @return this operation instance + * @throws IOException if a JAR could not be found + */ + public T launcherLibs(Path... jars) throws IOException { + return launcherLibsPaths(List.of(jars)); + } + + /** + * Provides the libraries for the Spring Boot loader launcher. + * + * @param jars one or more Java archives + * @return this operation instance + * @throws IOException if a JAR could not be found + */ + public T launcherLibsPaths(Collection jars) throws IOException { + return launcherLibs(jars.stream().map(Path::toFile).toList()); + } + + /** + * Provides the libraries for the Spring Boot loader launcher. + * + * @param jars one or more Java archives + * @return this operation instance + * @throws IOException if a JAR could not be found + */ + public T launcherLibsStrings(Collection jars) throws IOException { + return launcherLibs(jars.stream().map(File::new).toList()); } /** @@ -463,12 +517,22 @@ public T manifestAttributes(Map attributes) { * @param directories one or more source directories * @return this operation instance */ - public T sourceDirectories(File... directories) { - sourceDirectories_.addAll(List.of(directories)); + public T sourceDirectories(Collection directories) { + sourceDirectories_.addAll(directories); //noinspection unchecked return (T) this; } + /** + * Provides source directories that will be used for the archive creation. + * + * @param directories one or more source directories + * @return this operation instance + */ + public T sourceDirectories(File... directories) { + return sourceDirectories(List.of(directories)); + } + /** * Provides source directories that will be used for the archive creation. * @@ -476,9 +540,17 @@ public T sourceDirectories(File... directories) { * @return this operation instance */ public T sourceDirectories(String... directories) { - sourceDirectories_.addAll(Arrays.stream(directories).map(File::new).toList()); - //noinspection unchecked - return (T) this; + return sourceDirectoriesStrings(List.of(directories)); + } + + /** + * Provides source directories that will be used for the archive creation. + * + * @param directories one or more source directories + * @return this operation instance + */ + public T sourceDirectories(Path... directories) { + return sourceDirectoriesPaths(List.of(directories)); } /** @@ -490,6 +562,26 @@ public Collection sourceDirectories() { return sourceDirectories_; } + /** + * Provides source directories that will be used for the archive creation. + * + * @param directories one or more source directories + * @return this operation instance + */ + public T sourceDirectoriesPaths(Collection directories) { + return sourceDirectories(directories.stream().map(Path::toFile).toList()); + } + + /** + * Provides source directories that will be used for the archive creation. + * + * @param directories one or more source directories + * @return this operation instance + */ + public T sourceDirectoriesStrings(Collection directories) { + return sourceDirectories(directories.stream().map(File::new).toList()); + } + /** * Verifies that all the elements ({@link #mainClass() mainClass}, {@link #launcherClass() launcherClass} and * {@link #launcherLibs() launcherLibs}) required to create the archive have been provided, throws an diff --git a/src/main/java/rife/bld/extension/BootWarOperation.java b/src/main/java/rife/bld/extension/BootWarOperation.java index da4bd53..320e5ae 100644 --- a/src/main/java/rife/bld/extension/BootWarOperation.java +++ b/src/main/java/rife/bld/extension/BootWarOperation.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -151,6 +152,16 @@ public BootWarOperation providedLibs(Collection jars) { return this; } + /** + * Provides the libraries that will be used for the WAR creation in {@code /WEB-INF/lib-provided}. + * + * @param jars one or more Java archive files + * @return this operation instance + */ + public BootWarOperation providedLibs(String... jars) { + return providedLibsStrings(List.of(jars)); + } + /** * Provides the libraries that will be used for the WAR creation in {@code /WEB-INF/lib-provided}. * @@ -158,7 +169,47 @@ public BootWarOperation providedLibs(Collection jars) { * @return this operation instance */ public BootWarOperation providedLibs(File... jars) { - providedLibs_.addAll(List.of(jars)); + return providedLibs(List.of(jars)); + } + + /** + * Provides the libraries that will be used for the WAR creation in {@code /WEB-INF/lib-provided}. + * + * @param jars one or more Java archive files + * @return this operation instance + */ + public BootWarOperation providedLibs(Path... jars) { + return providedLibsPaths(List.of(jars)); + } + + /** + * Retrieves the libraries that will be used for the WAR creation in {@code /WEB-INF/lib-provided}. + * + * @return the list of Java archive files. + */ + public List providedLibs() { + return providedLibs_; + } + + /** + * Provides the libraries that will be used for the WAR creation in {@code /WEB-INF/lib-provided}. + * + * @param jars one or more Java archive files + * @return this operation instance + */ + public BootWarOperation providedLibsPaths(Collection jars) { + providedLibs_.addAll(jars.stream().map(Path::toFile).toList()); + return this; + } + + /** + * Provides the libraries that will be used for the WAR creation in {@code /WEB-INF/lib-provided}. + * + * @param jars one or more Java archive files + * @return this operation instance + */ + public BootWarOperation providedLibsStrings(Collection jars) { + providedLibs_.addAll(jars.stream().map(File::new).toList()); return this; } } diff --git a/src/test/java/rife/bld/extension/BootJarOperationTest.java b/src/test/java/rife/bld/extension/BootJarOperationTest.java index b7d0777..0e4f5e5 100644 --- a/src/test/java/rife/bld/extension/BootJarOperationTest.java +++ b/src/test/java/rife/bld/extension/BootJarOperationTest.java @@ -24,6 +24,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; @@ -159,6 +160,7 @@ class BootJarOperationTest { private static final String SPRING_BOOT = "spring-boot-" + BOOT_VERSION + ".jar"; private static final String SPRING_BOOT_ACTUATOR = "spring-boot-actuator-" + BOOT_VERSION + ".jar"; private static final String SPRING_BOOT_LOADER = "spring-boot-loader-" + BOOT_VERSION + ".jar"; + private static final String SRC_MAIN_JAVA = "src/main/java"; private StringBuilder readJarEntries(File jar) throws IOException { var jarEntries = new StringBuilder(); @@ -200,6 +202,37 @@ void testErrors() throws IOException { assertThat(bootWar.verifyExecute()).isTrue(); } + @Test + void testInfLibs() { + var op = new BootWarOperation(); + + var foo = new File(EXAMPLES_LIB_COMPILE + SPRING_BOOT); + op = op.infLibs(EXAMPLES_LIB_COMPILE + SPRING_BOOT); + assertThat(op.infLibs()).containsExactly(foo); + op.infLibs().clear(); + + op = op.infLibs(foo); + assertThat(op.infLibs()).containsExactly(foo); + op.infLibs().clear(); + + op = op.infLibs(foo.toPath()); + assertThat(op.infLibs()).containsExactly(foo); + op.infLibs().clear(); + + var bar = new File(EXAMPLES_LIB_COMPILE + SPRING_BOOT_ACTUATOR); + op.infLibs(EXAMPLES_LIB_COMPILE + SPRING_BOOT, EXAMPLES_LIB_COMPILE + SPRING_BOOT_ACTUATOR); + assertThat(op.infLibs()).containsExactly(foo, bar); + op.infLibs().clear(); + + op.infLibs(foo, bar); + assertThat(op.infLibs()).containsExactly(foo, bar); + op.infLibs().clear(); + + op.infLibs(foo.toPath(), bar.toPath()); + assertThat(op.infLibs()).containsExactly(foo, bar); + op.infLibs().clear(); + } + @Test @SuppressWarnings("PMD.AvoidDuplicateLiterals") void testJarExecute() throws Exception { @@ -274,16 +307,34 @@ void testJarProjectExecute() throws Exception { FileUtils.deleteDirectory(tmp_dir); } + @Test + void testLauncherLibs() throws IOException { + var op = new BootJarOperation(); + + var launcher = new File(EXAMPLES_LIB_STANDALONE + SPRING_BOOT_LOADER); + op = op.launcherLibs(EXAMPLES_LIB_STANDALONE + SPRING_BOOT_LOADER); + assertThat(op.launcherLibs()).containsExactly(launcher); + op.launcherLibs().clear(); + + op = op.launcherLibs(launcher); + assertThat(op.launcherLibs()).containsExactly(launcher); + op.launcherLibs().clear(); + + op = op.launcherLibs(launcher.toPath()); + assertThat(op.launcherLibs()).containsExactly(launcher); + op.launcherLibs().clear(); + } + @Test void testProject() throws IOException { var tmp_dir = Files.createTempDirectory("bootprjtmp").toFile(); var project = new CustomProject(tmp_dir); - var bootJar = new BootJarOperation().fromProject(project).sourceDirectories("src/main/java"); + var bootJar = new BootJarOperation().fromProject(project).sourceDirectories(SRC_MAIN_JAVA); assertThat(bootJar.mainClass()).as("mainClass").isEqualTo(MAIN_CLASS); assertThat(bootJar.sourceDirectories()).as("sourceDirectories.size").hasSize(3) .containsExactly(project.buildMainDirectory(), project.srcMainResourcesDirectory(), - new File("src/main/java")); + new File(SRC_MAIN_JAVA)); assertThat(bootJar.manifestAttributes()).as("manifestAttributes.size").hasSize(3); assertThat(bootJar.manifestAttributes().get("Manifest-Version")).as("Manifest-Version").isEqualTo("1.0"); assertThat(bootJar.manifestAttributes().get("Main-Class")).as("Main-Class").endsWith("JarLauncher"); @@ -299,6 +350,37 @@ void testProject() throws IOException { FileUtils.deleteDirectory(tmp_dir); } + @Test + void testSourceDirectories() { + var op = new BootJarOperation(); + + var src = new File(SRC_MAIN_JAVA); + op = op.sourceDirectories(SRC_MAIN_JAVA); + assertThat(op.sourceDirectories()).containsExactly(src); + op.sourceDirectories().clear(); + + op = op.sourceDirectories(src); + assertThat(op.sourceDirectories()).containsExactly(src); + op.sourceDirectories().clear(); + + op = op.sourceDirectories(src.toPath()); + assertThat(op.sourceDirectories()).containsExactly(src); + op.sourceDirectories().clear(); + + var test = new File("src/test/java"); + op.sourceDirectories(SRC_MAIN_JAVA, "src/test/java"); + assertThat(op.sourceDirectories()).containsExactly(src, test); + op.sourceDirectories().clear(); + + op.sourceDirectories(src, test); + assertThat(op.sourceDirectories()).containsExactly(src, test); + op.sourceDirectories().clear(); + + op.sourceDirectories(src.toPath(), test.toPath()); + assertThat(op.sourceDirectories()).containsExactly(src, test); + op.sourceDirectories().clear(); + } + @Test void testWarProjectExecute() throws Exception { var tmp_dir = Files.createTempDirectory("bootjartmp").toFile(); @@ -306,9 +388,9 @@ void testWarProjectExecute() throws Exception { new BootWarOperation() .fromProject(project) .launcherLibs(List.of(new File(EXAMPLES_LIB_STANDALONE + SPRING_BOOT_LOADER))) - .destinationDirectory(tmp_dir) - .infLibs(new File(EXAMPLES_LIB_COMPILE + SPRING_BOOT), - new File(EXAMPLES_LIB_COMPILE + SPRING_BOOT_ACTUATOR)) + .destinationDirectory(tmp_dir.toPath()) + .infLibs(Path.of(EXAMPLES_LIB_COMPILE + SPRING_BOOT), + Path.of(EXAMPLES_LIB_COMPILE + SPRING_BOOT_ACTUATOR)) .providedLibs(new File(EXAMPLES_LIB_RUNTIME + PROVIDED_LIB)) .execute(); @@ -339,6 +421,24 @@ void testWarProjectExecute() throws Exception { FileUtils.deleteDirectory(tmp_dir); } + @Test + void testWarProvidedLibs() { + var op = new BootWarOperation(); + + var foo = new File(EXAMPLES_LIB_RUNTIME + PROVIDED_LIB); + op = op.providedLibs(EXAMPLES_LIB_RUNTIME + PROVIDED_LIB); + assertThat(op.providedLibs()).containsExactly(foo); + op.providedLibs().clear(); + + op = op.providedLibs(foo); + assertThat(op.providedLibs()).containsExactly(foo); + op.providedLibs().clear(); + + op = op.providedLibs(foo.toPath()); + assertThat(op.providedLibs()).containsExactly(foo); + op.providedLibs().clear(); + } + static class CustomProject extends Project { CustomProject(File tmp) { super();