Use Collection/Map instead of List whenever applicable

This commit is contained in:
Erik C. Thauvin 2024-06-20 18:32:43 -07:00
parent 16f45fad1a
commit 3a08a9d845
Signed by: erik
GPG key ID: 776702A6A2DA330E
5 changed files with 120 additions and 85 deletions

View file

@ -26,10 +26,10 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.spi.ToolProvider;
@ -45,10 +45,10 @@ import java.util.spi.ToolProvider;
public abstract class AbstractBootOperation<T extends AbstractBootOperation<T>>
extends AbstractOperation<AbstractBootOperation<T>> {
private static final Logger LOGGER = Logger.getLogger(AbstractBootOperation.class.getName());
private final List<File> infLibs_ = new ArrayList<>();
private final List<File> launcherLibs_ = new ArrayList<>();
private final List<BootManifestAttribute> manifestAttributes_ = new ArrayList<>();
private final List<File> sourceDirectories_ = new ArrayList<>();
private final Collection<File> infLibs_ = new ArrayList<>();
private final Collection<File> launcherLibs_ = new ArrayList<>();
private final Map<String, String> manifestAttributes_ = new ConcurrentHashMap<>();
private final Collection<File> sourceDirectories_ = new ArrayList<>();
private File destinationDirectory_;
private String destinationFileName_;
private String launcherClass_;
@ -239,8 +239,8 @@ public abstract class AbstractBootOperation<T extends AbstractBootOperation<T>>
var manifest = new File(meta_inf_dir, "MANIFEST.MF").toPath();
try (var fileWriter = Files.newBufferedWriter(manifest)) {
for (var manifestAttribute : manifestAttributes()) {
fileWriter.write(manifestAttribute.name() + ": " + manifestAttribute.value() + System.lineSeparator());
for (var set : manifestAttributes_.entrySet()) {
fileWriter.write(set.getKey() + ": " + set.getValue() + System.lineSeparator());
}
}
}
@ -278,12 +278,24 @@ public abstract class AbstractBootOperation<T extends AbstractBootOperation<T>>
return (T) this;
}
/**
* 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(String... jars) {
infLibs_.addAll(Arrays.stream(jars).map(File::new).toList());
//noinspection unchecked
return (T) this;
}
/**
* Retrieves the libraries in {@code BOOT-INF} or {@code WEB-INF}.
*
* @return a list of Java archives
* @return the Java archives
*/
public List<File> infLibs() {
public Collection<File> infLibs() {
return infLibs_;
}
@ -321,9 +333,9 @@ public abstract class AbstractBootOperation<T extends AbstractBootOperation<T>>
/**
* Retrieves the Spring Boot loader launcher libraries.
*
* @return a list of Java archives
* @return the Java archives
*/
public List<File> launcherLibs() {
public Collection<File> launcherLibs() {
return launcherLibs_;
}
@ -332,10 +344,9 @@ public abstract class AbstractBootOperation<T extends AbstractBootOperation<T>>
*
* @param jars a collection of Java archives
* @return this operation instance
* @throws IOException if an error occurs
* @throws IOException if a JAR could not be found
*/
public T launcherLibs(Collection<File> jars) throws IOException {
if (!jars.isEmpty()) {
for (var j : jars) {
if (j.exists()) {
launcherLibs_.add(j);
@ -343,6 +354,46 @@ public abstract class AbstractBootOperation<T extends AbstractBootOperation<T>>
throw new IOException("Spring Boot loader launcher library not found: " + j);
}
}
//noinspection unchecked
return (T) this;
}
/**
* 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
*/
@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;
}
/**
* 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
*/
@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;
@ -377,17 +428,17 @@ public abstract class AbstractBootOperation<T extends AbstractBootOperation<T>>
* @return this operation instance
*/
public T manifestAttribute(String name, String value) {
manifestAttributes_.add(new BootManifestAttribute(name, value));
manifestAttributes_.put(name, value);
//noinspection unchecked
return (T) this;
}
/**
* Retrieves the list of attributes that will be put in the archive manifest.
* Retrieves the attributes that will be put in the archive manifest.
*
* @return a list of manifest attributes
* @return the manifest attributes
*/
public List<BootManifestAttribute> manifestAttributes() {
public Map<String, String> manifestAttributes() {
return manifestAttributes_;
}
@ -396,9 +447,10 @@ public abstract class AbstractBootOperation<T extends AbstractBootOperation<T>>
*
* @param attributes the manifest attributes
* @return this operation instance
* @see #manifestAttribute(String, String)
*/
public T manifestAttributes(Collection<BootManifestAttribute> attributes) {
manifestAttributes_.addAll(attributes);
public T manifestAttributes(Map<String, String> attributes) {
manifestAttributes_.putAll(attributes);
//noinspection unchecked
return (T) this;
}
@ -415,12 +467,24 @@ public abstract class AbstractBootOperation<T extends AbstractBootOperation<T>>
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(String... directories) {
sourceDirectories_.addAll(Arrays.stream(directories).map(File::new).toList());
//noinspection unchecked
return (T) this;
}
/**
* Retrieves the source directories that will be used for the archive creation.
*
* @return a list of directories
* @return the source directories
*/
public List<File> sourceDirectories() {
public Collection<File> sourceDirectories() {
return sourceDirectories_;
}

View file

@ -23,7 +23,7 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -89,7 +89,7 @@ public class BootJarOperation extends AbstractBootOperation<BootJarOperation> {
* {@link Project#standaloneClasspathJars() standaloneClasspathJars}</li>
* <li>The {@link #mainClass(String) main class} to {@link Project#mainClass() mainClass}</li>
* <li>The {@code Manifest-Version}, {@code Main-Class} and {@code Start-Class}
* {@link #manifestAttributes(Collection) manifest attributes}</li>
* {@link #manifestAttributes() manifest attributes}</li>
* <li>The {@link #sourceDirectories(File...) source directories} to
* {@link Project#buildMainDirectory() buildMainDirectory} and
* {@link Project#srcMainResourcesDirectory() srcMainResourcesDirectory}</li>
@ -107,11 +107,10 @@ public class BootJarOperation extends AbstractBootOperation<BootJarOperation> {
.launcherClass(BootUtils.launcherClass(project, "JarLauncher"))
.launcherLibs(project.standaloneClasspathJars())
.mainClass(project.mainClass())
.manifestAttributes(List.of(
new BootManifestAttribute("Manifest-Version", "1.0"),
new BootManifestAttribute("Main-Class", launcherClass()),
new BootManifestAttribute("Start-Class", mainClass())
))
.manifestAttributes(Map.of(
"Manifest-Version", "1.0",
"Main-Class", launcherClass(),
"Start-Class", mainClass()))
.sourceDirectories(project.buildMainDirectory(), project.srcMainResourcesDirectory());
}
}

View file

@ -1,28 +0,0 @@
/*
* Copyright 2023-2024 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 rife.bld.extension;
/**
* Constructs a new manifest attribute.
*
* @param name The attribute name
* @param value The attribute value
* @author <a href="https://erik.thauvin.net/">Erik C. Thauvin</a>
* @since 1.0
*/
public record BootManifestAttribute(String name, String value) {
}

View file

@ -25,6 +25,7 @@ import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -112,7 +113,7 @@ public class BootWarOperation extends AbstractBootOperation<BootWarOperation> {
* {@link Project#standaloneClasspathJars() standaloneClasspathJars}</li>
* <li>The {@link #mainClass(String) main class} to {@link Project#mainClass() mainClass}</li>
* <li>The {@code Manifest-Version}, {@code Main-Class} and {@code Start-Class}
* {@link #manifestAttributes(Collection) manifest attributes}</li>
* {@link #manifestAttributes() manifest attributes}</li>
* <li>The {@link #sourceDirectories(File...) source directories} to
* {@link Project#buildMainDirectory() buildMainDirectory} and
* {@link Project#srcMainResourcesDirectory() srcMainResourcesDirectory}</li>
@ -131,11 +132,10 @@ public class BootWarOperation extends AbstractBootOperation<BootWarOperation> {
.launcherClass(BootUtils.launcherClass(project, "WarLauncher"))
.launcherLibs(project.standaloneClasspathJars())
.mainClass(project.mainClass())
.manifestAttributes(List.of(
new BootManifestAttribute("Manifest-Version", "1.0"),
new BootManifestAttribute("Main-Class", launcherClass()),
new BootManifestAttribute("Start-Class", mainClass())
))
.manifestAttributes(Map.of(
"Manifest-Version", "1.0",
"Main-Class", launcherClass(),
"Start-Class", mainClass()))
.providedLibs(project.providedClasspathJars())
.sourceDirectories(project.buildMainDirectory(), project.srcMainResourcesDirectory());
}

View file

@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThatCode;
class BootJarOperationTest {
private static final String BLD = "bld-1.9.1.jar";
private static final String BOOT_VERSION = "3.3.0";
private static final String BOOT_VERSION = "3.3.1";
private static final String EXAMPLES_LIB_COMPILE = "examples/lib/compile/";
private static final String EXAMPLES_LIB_RUNTIME = "examples/lib/runtime/";
private static final String EXAMPLES_LIB_STANDALONE = "examples/lib/standalone/";
@ -180,7 +180,13 @@ class BootJarOperationTest {
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("class required");
assertThatCode(() -> new BootWarOperation().launcherLibs(List.of(new File("foo"))))
assertThatCode(() -> new BootWarOperation().launcherLibs(new File("foo")))
.as("foo")
.isInstanceOf(IOException.class)
.hasMessageContaining("not found");
assertThatCode(() -> new BootWarOperation().launcherLibs("bar"))
.as("bar")
.isInstanceOf(IOException.class)
.hasMessageContaining("not found");
@ -221,7 +227,6 @@ class BootJarOperationTest {
"BOOT-INF/classes/rife/bld/extension/\n" +
"BOOT-INF/classes/rife/bld/extension/AbstractBootOperation.class\n" +
"BOOT-INF/classes/rife/bld/extension/BootJarOperation.class\n" +
"BOOT-INF/classes/rife/bld/extension/BootManifestAttribute.class\n" +
"BOOT-INF/classes/rife/bld/extension/BootUtils.class\n" +
"BOOT-INF/classes/rife/bld/extension/BootWarOperation.class\n" +
"BOOT-INF/lib/\n" +
@ -239,9 +244,9 @@ class BootJarOperationTest {
new BootJarOperation()
.fromProject(new CustomProject(new File(".")))
.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.getAbsolutePath())
.infLibs(new File(EXAMPLES_LIB_COMPILE + SPRING_BOOT).getAbsolutePath(),
new File(EXAMPLES_LIB_COMPILE + SPRING_BOOT_ACTUATOR).getAbsolutePath())
.execute();
var jarFile = new File(tmp_dir, "test_project-0.0.1-boot.jar");
@ -256,7 +261,6 @@ class BootJarOperationTest {
"BOOT-INF/classes/rife/bld/extension/\n" +
"BOOT-INF/classes/rife/bld/extension/AbstractBootOperation.class\n" +
"BOOT-INF/classes/rife/bld/extension/BootJarOperation.class\n" +
"BOOT-INF/classes/rife/bld/extension/BootManifestAttribute.class\n" +
"BOOT-INF/classes/rife/bld/extension/BootUtils.class\n" +
"BOOT-INF/classes/rife/bld/extension/BootWarOperation.class\n" +
"BOOT-INF/lib/\n" +
@ -278,14 +282,11 @@ class BootJarOperationTest {
assertThat(bootJar.mainClass()).as("mainClass").isEqualTo(MAIN_CLASS);
assertThat(bootJar.sourceDirectories()).as("sourceDirectories.size").hasSize(2);
assertThat(bootJar.manifestAttributes()).as("manifestAttributes.size").hasSize(3);
assertThat(bootJar.manifestAttributes().get(0)).as("Manifest-Version")
.isEqualTo(new BootManifestAttribute("Manifest-Version", "1.0"));
assertThat(bootJar.manifestAttributes().get(1).value()).as("Main-Class").endsWith("JarLauncher");
assertThat(bootJar.manifestAttributes().get(2)).as("Start-Class")
.isEqualTo(new BootManifestAttribute("Start-Class", MAIN_CLASS));
assertThat(bootJar.manifestAttributes().get("Manifest-Version")).as("Manifest-Version").isEqualTo("1.0");
assertThat(bootJar.manifestAttributes().get("Main-Class")).as("Main-Class").endsWith("JarLauncher");
assertThat(bootJar.manifestAttributes().get("Start-Class")).as("Start-Class").isEqualTo(MAIN_CLASS);
assertThat(bootJar.manifestAttribute("Manifest-Test", "tsst")
.manifestAttributes()).as("Manifest-Test").hasSize(4)
.element(3).extracting(BootManifestAttribute::name).isEqualTo("Manifest-Test");
.manifestAttributes().get("Manifest-Test")).as("Manifest-Test").isEqualTo("tsst");
assertThat(bootJar.destinationDirectory()).as("destinationDirectory").isDirectory();
assertThat(bootJar.destinationDirectory().getAbsolutePath()).as("destinationDirectory")
.isEqualTo(Path.of(tmp_dir.getPath(), "build", "dist").toString());
@ -323,7 +324,6 @@ class BootJarOperationTest {
"WEB-INF/classes/rife/bld/extension/\n" +
"WEB-INF/classes/rife/bld/extension/AbstractBootOperation.class\n" +
"WEB-INF/classes/rife/bld/extension/BootJarOperation.class\n" +
"WEB-INF/classes/rife/bld/extension/BootManifestAttribute.class\n" +
"WEB-INF/classes/rife/bld/extension/BootUtils.class\n" +
"WEB-INF/classes/rife/bld/extension/BootWarOperation.class\n" +
"WEB-INF/lib/\n" +