From 547b20a242ca0e1b2112d304c795b9ba0e0bb5f0 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 1 Aug 2024 11:41:29 -0700 Subject: [PATCH 01/27] Draft implementations of JpackageOperation, JmodOperation and JlinkOperation --- .../AbstractToolProviderOperation.java | 142 +++ .../rife/bld/operations/JlinkOperation.java | 52 ++ .../rife/bld/operations/JlinkOptions.java | 284 ++++++ .../rife/bld/operations/JmodOperation.java | 88 ++ .../java/rife/bld/operations/JmodOptions.java | 291 ++++++ .../bld/operations/JpackageOperation.java | 52 ++ .../rife/bld/operations/JpackageOptions.java | 843 ++++++++++++++++++ .../rife/bld/operations/ZipCompression.java | 30 + .../bld/operations/TestJlinkOperation.java | 26 + .../bld/operations/TestJmodOperation.java | 26 + .../bld/operations/TestJpackageOperation.java | 56 ++ 11 files changed, 1890 insertions(+) create mode 100644 src/main/java/rife/bld/operations/AbstractToolProviderOperation.java create mode 100644 src/main/java/rife/bld/operations/JlinkOperation.java create mode 100644 src/main/java/rife/bld/operations/JlinkOptions.java create mode 100644 src/main/java/rife/bld/operations/JmodOperation.java create mode 100644 src/main/java/rife/bld/operations/JmodOptions.java create mode 100644 src/main/java/rife/bld/operations/JpackageOperation.java create mode 100644 src/main/java/rife/bld/operations/JpackageOptions.java create mode 100644 src/main/java/rife/bld/operations/ZipCompression.java create mode 100644 src/test/java/rife/bld/operations/TestJlinkOperation.java create mode 100644 src/test/java/rife/bld/operations/TestJmodOperation.java create mode 100644 src/test/java/rife/bld/operations/TestJpackageOperation.java diff --git a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java new file mode 100644 index 0000000..6113069 --- /dev/null +++ b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java @@ -0,0 +1,142 @@ +/* + * Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com) + * Licensed under the Apache License, Version 2.0 (the "License") + */ +package rife.bld.operations; + +import rife.bld.operations.exceptions.ExitStatusException; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.spi.ToolProvider; + +/** + * Provides common features for tool providers. + * + * @author Erik C. Thauvin + * @since 2.0.2 + */ +public abstract class AbstractToolProviderOperation> + extends AbstractOperation> { + private final Map toolArgs_ = new HashMap<>(); + private final String toolName_; + + /** + * Provides the name of the tool. + * + * @param toolName the tool name + */ + public AbstractToolProviderOperation(String toolName) { + toolName_ = toolName; + } + + /** + * Converts arguments to a list. + * + * @param args the argument-value pairs + * @return the arguments list + */ + static List argsToList(Map args) { + var list = new ArrayList(); + for (String arg : args.keySet()) { + var value = args.get(arg); + list.add(arg); + if (value != null && !value.isEmpty()) { + list.add(value); + } + } + return list; + } + + /** + * Adds tool command line argument. + * + * @param arg the argument to add + * @return this operation + */ + public T toolArg(String arg) { + toolArgs_.put(arg, null); + return (T) this; + } + + /** + * Add tool command line argument. + * + * @param arg the argument + * @param value the value + * @return this operation + */ + public T toolArg(String arg, String value) { + toolArgs_.put(arg, value); + return (T) this; + } + + /** + * Adds tool command line arguments. + * + * @param args the argument-value pairs to add + * @return this operation + */ + protected T toolArgs(Map args) { + toolArgs_.putAll(args); + return (T) this; + } + + /** + * Clears the tool command line arguments. + * + * @return this operation + */ + protected T clearToolArguments() { + toolArgs_.clear(); + return (T) this; + } + + @Override + public void execute() throws Exception { + if (toolArgs_.isEmpty()) { + System.err.println("No " + toolName_ + " arguments specified."); + throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); + } + var tool = ToolProvider.findFirst(toolName_).orElseThrow(() -> + new IllegalStateException("No " + toolName_ + " tool found.")); + + var argsList = argsToList(toolArgs_); + + var stderr = new StringWriter(); + var stdout = new StringWriter(); + try (var err = new PrintWriter(stderr); var out = new PrintWriter(stdout)) { + var status = tool.run(out, err, argsList.toArray(new String[0])); + out.flush(); + err.flush(); + + if (status != 0) { + System.out.println(tool.name() + " " + String.join(" ", argsList)); + } + + var output = stdout.toString(); + if (!output.isBlank()) { + System.out.println(output); + } + var error = stderr.toString(); + if (!error.isBlank()) { + System.err.println(error); + } + + ExitStatusException.throwOnFailure(status); + } + } + + /** + * Returns the tool command line arguments. + * + * @return the arguments + */ + public Map toolArgs() { + return toolArgs_; + } +} diff --git a/src/main/java/rife/bld/operations/JlinkOperation.java b/src/main/java/rife/bld/operations/JlinkOperation.java new file mode 100644 index 0000000..c3d5d44 --- /dev/null +++ b/src/main/java/rife/bld/operations/JlinkOperation.java @@ -0,0 +1,52 @@ +/* + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ + +package rife.bld.operations; + +import java.util.Map; + +/** + * Create run-time images using the jlink tool. + * + * @author Erik C. Thauvin + * @since 2.0.2 + */ +public class JlinkOperation extends AbstractToolProviderOperation { + private final JlinkOptions jlinkOptions_ = new JlinkOptions(); + + public JlinkOperation() { + super("jlink"); + } + + @Override + public void execute() throws Exception { + toolArgs(jlinkOptions_); + super.execute(); + } + + /** + * Retrieves the list of options for the jlink tool. + *

+ * This is a modifiable list that can be retrieved and changed. + * + * @return the list of jlink options + */ + public JlinkOptions jlinkOptions() { + return jlinkOptions_; + } + + /** + * Provides a list of options to provide to the jlink tool. + *

+ * A copy will be created to allow this list to be independently modifiable. + * + * @param options the argument-value pairs + * @return this operation instance + */ + public JlinkOperation jlinkOptions(Map options) { + jlinkOptions_.putAll(options); + return this; + } +} diff --git a/src/main/java/rife/bld/operations/JlinkOptions.java b/src/main/java/rife/bld/operations/JlinkOptions.java new file mode 100644 index 0000000..d9969b2 --- /dev/null +++ b/src/main/java/rife/bld/operations/JlinkOptions.java @@ -0,0 +1,284 @@ +/** + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ +package rife.bld.operations; + +import java.util.HashMap; + +/** + * Options for jlink tool. + * + * @author Erik C. Thauvin + * @since 2.0.2 + */ +public class JlinkOptions extends HashMap { + /** + * All Modules Path. + */ + public final static String ALL_MODULE_PATH = "ALL-MODULE-PATH"; + + /** + * Root modules to resolve in addition to the initial modules. + *

+ * Module can also be {@link #ALL_MODULE_PATH} + * + * @param modules one or more module + * @return this map of options + */ + public JlinkOptions addModules(String... modules) { + put("--add-modules", String.join(",", modules)); + return this; + } + + /** + * Link in service provider modules and their dependencies. + * + * @param bindServices {@code true} to bind services, {@code false} otherwise + * @return this map of options + */ + public JlinkOptions bindServices(boolean bindServices) { + if (bindServices) { + put("--bind-services", null); + } else { + remove("--bind-services"); + } + return this; + } + + /** + * Compression to use in compressing resources. + *

+ * Where {@link ZipCompression#ZIP_0 ZIP_0} provides no compression and {@link ZipCompression#ZIP_9 ZIP_9} provides the + * best compression. + *

Default is {@link ZipCompression#ZIP_6 ZIP_6} + * + * @param compression the {@link ZipCompression compression} level + * @return this map of options + */ + public JlinkOptions compress(ZipCompression compression) { + put("--compress", compression.level); + return this; + } + + /** + * Disable the plugin mentioned. + * + * @param plugin the plugin name + * @return this map of options + */ + public JlinkOptions disablePlugin(String plugin) { + put("--disable-plugin", plugin); + return this; + } + + /** + * Byte order of generated jimage. + *

+ * Default: native + * + * @param endian the byte order + * @return this map of options + */ + public JlinkOptions endian(Endian endian) { + put("--endian", endian.byteOrder); + return this; + } + + /** + * Read options from file. + * + * @param filename the filename + * @return this map of options + */ + public JlinkOptions filename(String filename) { + put("@" + filename, null); + return this; + } + + /** + * Suppress a fatal error when signed modular JARs are linked in the image. + * + * @param ignoreSigningInformation {@code true} to ignore signing information, {@code false} otherwise + * @return this map of options + */ + public JlinkOptions ignoreSigningInformation(boolean ignoreSigningInformation) { + if (ignoreSigningInformation) { + put("--ignore-signing-information", null); + } else { + remove("--ignore-signing-information"); + } + return this; + } + + /** + * Add a launcher command of the given name for the module. + * + * @param name the name + * @param module the module + * @return this map of options + */ + public JlinkOptions launcher(String name, String module) { + put("--launcher", name + "=" + module); + return this; + } + + /** + * Add a launcher command of the given name for the module and the main class. + * + * @param name the name + * @param module the module + * @param mainClass the main class + * @return this map of options + */ + public JlinkOptions launcher(String name, String module, String mainClass) { + put("--launcher", name + "=" + module + "/" + mainClass); + return this; + } + + /** + * Limit the universe of observable modules. + * + * @param module one or more module + * @return this map of options + */ + public JlinkOptions limitModule(String... module) { + put("--limit-modules", String.join(",", module)); + return this; + } + + /** + * Module path. + *

+ * If not specified, the JDKs jmods directory will be used, if it exists. If specified, but it does not contain the + * java.base module, the JDKs jmods directory will be added, if it exists. + * + * @param path the module path + * @return this map of options + */ + public JlinkOptions modulePath(String path) { + put("--module-path", path); + return this; + } + + /** + * Exclude include header files. + * + * @param noHeaderFiles {@code true} to exclude header files, {@code false} otherwise + * @return this map of options + */ + public JlinkOptions noHeaderFiles(boolean noHeaderFiles) { + if (noHeaderFiles) { + put("--no-header-files", null); + } else { + remove("--no-header-files"); + } + return this; + } + + /** + * Exclude man pages. + * + * @param noManPages {@code true} to exclude man pages, {@code false} otherwise + * @return this map of options + */ + public JlinkOptions noManPages(boolean noManPages) { + if (noManPages) { + put("--no-man-pages", null); + } else { + remove("--no-man-pages"); + } + return this; + } + + /** + * Location of output path. + * + * @param path the output path + * @return this map of options + */ + public JlinkOptions output(String path) { + put("--output", path); + return this; + } + + /** + * Suggest providers that implement the given service types from the module path. + * + * @param filename the filename + * @return this map of options + */ + public JlinkOptions saveOpts(String filename) { + put("--save-opts", filename); + return this; + } + + /** + * Strip debug information. + * + * @param stripDebug {@code true} to strip debug info, {@code false} otherwise + * @return this map of options + */ + public JlinkOptions stripDebug(boolean stripDebug) { + if (stripDebug) { + put("--strip-debug", null); + } else { + remove("--strip-debug"); + } + return this; + } + + /** + * Strip the native commands. + * + * @param stripNativeCommands {@code true} to strip, {@code false} otherwise + * @return this map of options + */ + public JlinkOptions stripNativeCommands(boolean stripNativeCommands) { + if (stripNativeCommands) { + put("--strip-native-commands", null); + } else { + remove("--strip-native-commands"); + } + return this; + } + + /** + * Suggest providers that implement the given service types from the module path. + * + * @param name one or more provider name + * @return this map of options + */ + public JlinkOptions suggestProviders(String... name) { + put("--suggest-providers", String.join(",", name)); + return this; + } + + /** + * Enable verbose tracing + * + * @param verbose {@code true} to enable verbose tracing, {@code false} otherwise. + * @return this map of options + */ + public JlinkOptions verbose(boolean verbose) { + if (verbose) { + put("--verbose", null); + } else { + remove("--verbose"); + } + return this; + } + + /** + * The byte orders. + */ + public enum Endian { + BIG("big"), LITTLE("little"); + + public final String byteOrder; + + Endian(String byteOrder) { + this.byteOrder = byteOrder; + } + } +} diff --git a/src/main/java/rife/bld/operations/JmodOperation.java b/src/main/java/rife/bld/operations/JmodOperation.java new file mode 100644 index 0000000..071f703 --- /dev/null +++ b/src/main/java/rife/bld/operations/JmodOperation.java @@ -0,0 +1,88 @@ +/* + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ + +package rife.bld.operations; + +import rife.bld.operations.exceptions.ExitStatusException; + +import java.util.Map; + +/** + * Create JMOD files with the jmod tool. + * + * @author Erik C. Thauvin + * @since 2.0.2 + */ +public class JmodOperation extends AbstractToolProviderOperation { + private final JmodOptions jmodOptions_ = new JmodOptions(); + private OperationMode operationMode_; + + public JmodOperation() { + super("jmod"); + } + + @Override + public void execute() throws Exception { + if (operationMode_ == null) { + System.err.println("Operation mode not set."); + throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); + } + toolArg(operationMode_.mode); + toolArgs(jmodOptions_); + super.execute(); + } + + /** + * Retrieves the list of options for the jmod tool. + *

+ * This is a modifiable list that can be retrieved and changed. + * + * @return the list of jmod options + */ + public JmodOptions jmodOptions() { + return jmodOptions_; + } + + /** + * Provides a list of options to provide to the jmod tool. + *

+ * A copy will be created to allow this list to be independently modifiable. + * + * @param options the list of jmod options + * @return this operation instance + */ + public JmodOperation jmodOptions(Map options) { + jmodOptions_.putAll(options); + return this; + } + + /** + * Provides the required {@link OperationMode operation mode}. + * + * @param mode the mode + * @return this operation instance + */ + public JmodOperation operationMode(OperationMode mode) { + operationMode_ = mode; + return this; + } + + /** + * The operation modes. + */ + public enum OperationMode { + CREATE("create"), + DESCRIBE("describe"), + EXTRACT("extract"), + HASH("hash"), + LIST("list"); + + final String mode; + + OperationMode(String mode) { + this.mode = mode; + } + } +} diff --git a/src/main/java/rife/bld/operations/JmodOptions.java b/src/main/java/rife/bld/operations/JmodOptions.java new file mode 100644 index 0000000..acd7152 --- /dev/null +++ b/src/main/java/rife/bld/operations/JmodOptions.java @@ -0,0 +1,291 @@ +/** + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ +package rife.bld.operations; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; + +/** + * Options for jmod tool. + * + * @author Erik C. Thauvin + * @since 2.0.2 + */ +public class JmodOptions extends HashMap { + /** + * Application jar files|dir containing classes. + * + * @param classpath the classpath + * @return this map of options + */ + public JmodOptions classpath(String classpath) { + put("--class-path", classpath); + return this; + } + + /** + * Location of native commands. + * + * @param path the location + * @return this map of options + */ + public JmodOptions cmds(String path) { + put("--cmds", path); + return this; + } + + /** + * Compression to use when creating the JMOD archive. + *

+ * Where {@link ZipCompression#ZIP_0 ZIP_0} provides no compression and {@link ZipCompression#ZIP_9 ZIP_9} provides the + * best compression. + *

Default is {@link ZipCompression#ZIP_6 ZIP_6} + * + * @param compression the {@link ZipCompression compression} level + * @return this map of options + */ + public JmodOptions compress(ZipCompression compression) { + put("--compress", compression.level); + return this; + } + + /** + * Location of user-editable config files + * + * @param path the path to the config files + * @return this map of options + */ + public JmodOptions config(String path) { + put("--config", path); + return this; + } + + /** + * Date and time for the timestamps of entries. + * + * @param date the date + * @return this map of options + */ + public JmodOptions date(ZonedDateTime date) { + put("--date", date.format(DateTimeFormatter.ISO_INSTANT)); + return this; + } + + /** + * Target directory for extract + * + * @param path the directory path + * @return this map of options + */ + public JmodOptions dir(String path) { + put("--dir", path); + return this; + } + + /** + * Exclude from the default root set of modules. + * + * @param doNotResolveByDefault {@code true} to not resolve, {@code false} otherwise + * @return this map of options + */ + public JmodOptions doNotResolveByDefault(boolean doNotResolveByDefault) { + if (doNotResolveByDefault) { + put("--do-not-resolve-by-default", null); + } else { + remove("--do-not-resolve-by-default"); + } + return this; + } + + /** + * Dry run of hash mode. + * + * @param dryRun {@code true} for dry run, {@code false} otherwise + * @return this list of operation + */ + public JmodOptions dryRun(boolean dryRun) { + if (dryRun) { + put("--dry-run", null); + } else { + remove("--dry-run"); + } + return this; + } + + /** + * Exclude files matching the supplied pattern list. + * + * @param pattern one or more pattern + * @return the list of options + */ + public JmodOptions exclude(FilePattern... pattern) { + var args = new ArrayList(); + for (var p : pattern) { + if (p.type == FilePatternType.GLOB) { + args.add("glob:" + p.pattern); + } else if (p.type == FilePatternType.REGEX) { + args.add("regex:" + p.pattern); + } + } + put("--exclude", String.join(",", args)); + return this; + } + + /** + * Read options from the specified file. + * + * @param filename the filename + * @return this map of options + */ + public JmodOptions filename(String filename) { + put("@" + filename, null); + return this; + } + + /** + * Compute and record hashes to tie a packaged module with modules matching the given regular expression pattern and + * depending upon it directly or indirectly. The hashes are recorded in the JMOD file being created, or a JMOD file + * or modular JAR on the module path specified the jmod hash command. + * + * @param regexPattern the regular expression pattern + * @return this map of options + */ + public JmodOptions hashModules(String regexPattern) { + put("--hash-modules", regexPattern); + return this; + } + + /** + * Location of header files. + * + * @param path the location + * @return this map of options + */ + public JmodOptions headerFiles(String path) { + put("--header-files", path); + return this; + } + + /** + * Location of legal notices. + * + * @param path the location + * @return this map of options + */ + public JmodOptions legalNotices(String path) { + put("--legal-notices", path); + return this; + } + + /** + * Location of native libraries. + * + * @param path the location + * @return this map of options + */ + public JmodOptions libs(String path) { + put("--libs", path); + return this; + } + + /** + * Main class. + * + * @param name the class name + * @return this list of operation + */ + public JmodOptions mainClass(String name) { + put("--main-class", name); + return this; + } + + /** + * Location of man pages. + * + * @param path the location + * @return this map of options + */ + public JmodOptions manPages(String path) { + put("--man-pages", path); + return this; + } + + /** + * Module path. + * + * @param path the module path + * @return this map of options + */ + public JmodOptions modulePath(String path) { + put("--module-path", path); + return this; + } + + /** + * Module version. + * + * @param version the module version. + * @return this map of options + */ + public JmodOptions moduleVersion(String version) { + put("--module-version", version); + return this; + } + + /** + * Target platform. + * + * @param platform the platform + * @return this list of operation + */ + public JmodOptions targetPlatform(String platform) { + put("--target-platform", platform); + return this; + } + + /** + * Hint for a tool to issue a warning if the module is resolved. + * + * @param reason the reason + * @return this map of options + */ + public JmodOptions warnIfResolved(ResolvedReason reason) { + put("--warn-if-resolved", reason.reason); + return this; + } + + /** + * The resolved reasons. + */ + public enum ResolvedReason { + DEPRECATED("deprecated"), + DEPRECATED_FOR_REMOVAL("deprecated-for-removal"), + INCUBATING("incubating"); + + final String reason; + + ResolvedReason(String reason) { + this.reason = reason; + } + } + + /** + * The file pattern types. + */ + public enum FilePatternType { + GLOB, REGEX + } + + /** + * Defines a file pattern and pattern type. + * + * @param type the pattern type + * @param pattern the pattern + */ + public record FilePattern(FilePatternType type, String pattern) { + } +} diff --git a/src/main/java/rife/bld/operations/JpackageOperation.java b/src/main/java/rife/bld/operations/JpackageOperation.java new file mode 100644 index 0000000..5fbdf0b --- /dev/null +++ b/src/main/java/rife/bld/operations/JpackageOperation.java @@ -0,0 +1,52 @@ +/* + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ + +package rife.bld.operations; + +import java.util.Map; + +/** + * Package self-contained Java applications with the jpackage tool. + * + * @author Erik C. Thauvin + * @since 2.0.2 + */ +public class JpackageOperation extends AbstractToolProviderOperation { + private final JpackageOptions jpackageOptions_ = new JpackageOptions(); + + public JpackageOperation() { + super("jpackage"); + } + + @Override + public void execute() throws Exception { + toolArgs(jpackageOptions_); + super.execute(); + } + + /** + * Retrieves the list of options for the jpackage tool. + *

+ * This is a modifiable list that can be retrieved and changed. + * + * @return the map of jpackage options + */ + public JpackageOptions jpackageOptions() { + return jpackageOptions_; + } + + /** + * Provides a list of options to provide to the jpackage tool. + *

+ * A copy will be created to allow this list to be independently modifiable. + * + * @param options the map of jpackage options + * @return this operation instance + */ + public JpackageOperation jpackageOptions(Map options) { + jpackageOptions_.putAll(options); + return this; + } +} diff --git a/src/main/java/rife/bld/operations/JpackageOptions.java b/src/main/java/rife/bld/operations/JpackageOptions.java new file mode 100644 index 0000000..0167fd6 --- /dev/null +++ b/src/main/java/rife/bld/operations/JpackageOptions.java @@ -0,0 +1,843 @@ +/** + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ +package rife.bld.operations; + +import java.util.HashMap; + +/** + * Options for jpackage tool. + * + * @author Erik C. Thauvin + * @since 2.0.2 + */ + +public class JpackageOptions extends HashMap { + /** + * URL of the application's home page. + * + * @param url the URL + * @return this map of options + */ + public JpackageOptions aboutUrl(String url) { + put("--about-url", url); + return this; + } + + /** + * List of application launchers. + *

+ * The main application launcher will be built from the command line options. Additional alternative launchers + * can be built using this option, and this option can be used to build multiple additional launchers. + * + * @param launcher one or more {@link Launcher} + * @return this map of options + */ + public JpackageOptions addLauncher(Launcher... launcher) { + for (var l : launcher) { + put("--add-launcher", l.name + '=' + l.path); + } + return this; + } + + /** + * List of modules to add. + *

+ * This module list, along with the main module (if specified) will be passed to jlink as the + * {@link JlinkOptions#addModules(String...) addModules} argument. If not specified, either just the main module + * (if {@link #module(String, String) module} is specified), or the default set of modules (if + * {@link #mainJar(String) mainJar} is specified) are used. + * + * @param modules one or more module + * @return this map of options + */ + public JpackageOptions addModules(String... modules) { + put("--add-modules", String.join(",", modules)); + return this; + } + + /** + * List of paths to files and/or directories to add to the application payload. + * + * @param additionalContent one or more path + * @return this map of options + */ + public JpackageOptions appContent(String... additionalContent) { + put("--app-content", String.join(",", additionalContent)); + return this; + } + + /** + * Options to pass to the Java runtime. + * + * @param options the options + * @return this map of options + */ + public JpackageOptions javaOptions(String... options) { + put("--java-options", String.join(" ", options)); + return this; + } + + /** + * Location of the predefined application image that is used to build an installable package. + * + * @param path absolute path or relative to the current directory + * @return this map of options + */ + public JpackageOptions appImage(String path) { + put("--app-image", path); + return this; + } + + /** + * Version of the application and/or package. + * + * @param version the version + * @return this map of options + */ + public JpackageOptions appVersion(String version) { + put("--app-version", version); + return this; + } + + /** + * Command line arguments to pass to main class if no command line arguments are given to the launcher. + * + * @param argument one or more argument + * @return this map of options + */ + public JpackageOptions arguments(String... argument) { + put("--arguments", String.join(" ", argument)); + return this; + } + + /** + * Copyright of the application. + * + * @param copyright the copyright + * @return this map of options + */ + public JpackageOptions copyright(String copyright) { + put("--copyright", copyright); + return this; + } + + /** + * Description of the application. + * + * @param description the description + * @return this map of options + */ + public JpackageOptions description(String description) { + put("--description", description); + return this; + } + + /** + * Path where generated output file is placed + * + * @param path absolute path or relative to the current directory + * @return this map of options + */ + public JpackageOptions dest(String path) { + put("--dest", path); + return this; + } + + /** + * Path to a Properties file that contains list of key, value pairs. + *

+ * The keys {@code extension}, {@code mime-type}, {@code icon}, and {@code description} can be used to describe the + * association. + * + * @param path absolute path or relative to the current directory + * @return this map of options + */ + public JpackageOptions fileAssociations(String... path) { + put("--file-associations", String.join(",", path)); + return this; + } + + /** + * Read options and/or mode from a file. + * + * @param filename the filename + * @return this map of options + */ + public JpackageOptions filename(String filename) { + put("@" + filename, null); + return this; + } + + /** + * Path of the icon of the application package/ + * + * @param path absolute path or relative to the current directory + * @return this map of options + */ + public JpackageOptions icon(String path) { + put("--icon", path); + return this; + } + + /** + * Path of the input directory that contains the files to be packaged. + *

+ * All files in the input directory will be packaged into the application image. + * + * @param path absolute path or relative to the current directory + * @return this map of options + */ + public JpackageOptions input(String path) { + put("--input", path); + return this; + } + + /** + * Absolute path of the installation directory of the application + * + * @param path the absolute directory path + * @return this map of options + */ + public JpackageOptions installDir(String path) { + put("--install-dir", path); + return this; + } + + /** + * List of options to pass to jlink. + *

+ * If not specified, defaults to {@link JlinkOptions#stripNativeCommands(boolean) stripNativeCommands} + * {@link JlinkOptions#stripDebug(boolean) stripDebug} {@link JlinkOptions#noManPages(boolean) noManPages} + * {@link JlinkOptions#noHeaderFiles(boolean) noHeaderFiles}. + * + * @param options the {@link JlinkOptions} + * @return this map of options + */ + public JpackageOptions jlinkOptions(JlinkOptions options) { + put("--jlink-options", String.join(" ", AbstractToolProviderOperation.argsToList(options))); + return this; + } + + /** + * Request to create an installer that will register the main application launcher as a background service-type + * application. + * + * @param launcherAsService {@code true} to register the launcher as a service; {@code false} otherwise + * @return this map of options + */ + public JpackageOptions launcherAsService(boolean launcherAsService) { + if (launcherAsService) { + put("--launcher-as-service", null); + } else { + remove("--launcher-as-service"); + } + return this; + } + + /** + * Path to the license file + * + * @param path absolute path or relative to the current directory + * @return this map of options + */ + public JpackageOptions licenseFile(String path) { + put("--license-file", path); + return this; + } + + /** + * Group value of the RPM {@code .spec} file or Section value of DEB control file + * + * @param appCategory the application category + * @return this map of options + */ + public JpackageOptions linuxAppCategory(String appCategory) { + put("--linux-app-category", appCategory); + return this; + } + + /** + * Release value of the RPM {@code .spec} file or Debian revision value of the DEB control file. + * + * @param appRelease the release value + * @return this map of options + */ + public JpackageOptions linuxAppRelease(String appRelease) { + put("--linux-app-release", appRelease); + return this; + } + + /** + * Maintainer for .deb package. + * + * @param maintainer the maintainer + * @return this map of options + */ + public JpackageOptions linuxDebMaintainer(String maintainer) { + put("--linux-deb-maintainer", maintainer); + return this; + } + + /** + * Menu group this application is placed in. + * + * @param menuGroup the menu group + * @return this map of options + */ + public JpackageOptions linuxMenuGroup(String menuGroup) { + put("--linux-menu-group", menuGroup); + return this; + } + + /** + * Required packages or capabilities for the application. + * + * @param packageDeps the package dependencies + * @return this list of operation + */ + public JpackageOptions linuxPackageDeps(String packageDeps) { + put("--linux-package-deps", packageDeps); + return this; + } + + /** + * Name for Linux package, defaults to the application name. + * + * @param packageName the package name + * @return this map of options + */ + public JpackageOptions linuxPackageName(String packageName) { + put("--linux-package-name", packageName); + return this; + } + + /** + * Type of the license ({@code License: } of the RPM .spec) + * + * @param licenseType the license type + * @return this map of options + */ + public JpackageOptions linuxRpmLicenseType(String licenseType) { + put("--linux-rpm-license-type", licenseType); + return this; + } + + /** + * Creates a shortcut for the application. + * + * @param shortcut {@code true| to create a shortcut, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions linuxShortcut(boolean shortcut) { + if (shortcut) { + put("--linux-shortcut", null); + } else { + remove("--linux-shortcut"); + } + return this; + } + + /** + * Qualified name of the application main class to execute. + *

+ * This option can only be used if {@link #mainJar(String) mainJar} is specified. + * + * @param mainClass the main class + * @return this map of options + */ + public JpackageOptions mainClass(String mainClass) { + put("--main-class", mainClass); + return this; + } + + /** + * The main JAR of the application; containing the main class. + *

+ * Either {@link #module(String, String) module} or {@link #mainJar(String) mainJar} option can be specified but not both. + * + * @param jar the path relative to the input path + * @return this map of options + */ + public JpackageOptions mainJar(String jar) { + put("--main-jar", jar); + return this; + } + + /** + * The main module and main class of the application. + *

+ * This module must be located on the {@link #modulePath(String) module path}. + *

+ * When this option is specified, the main module will be linked in the Java runtime image. + *

+ * Either {@link #module(String, String) module} or {@link #mainJar(String) mainJar} option can be specified but not both. + * + * @param name the module name + * @return this list of operation + */ + public JpackageOptions module(String name) { + put("--module", name); + return this; + } + + /** + * The main module and main class of the application. + *

+ * This module must be located on the {@link #modulePath(String) module path}. + *

+ * When this option is specified, the main module will be linked in the Java runtime image. + *

+ * Either {@link #module(String, String) module} or {@link #mainJar(String) mainJar} option can be specified but not both. + * + * @param name the module name + * @param mainClass the main class + * @return this map of options + */ + public JpackageOptions module(String name, String mainClass) { + put("--module-name", name + "/" + mainClass); + return this; + } + + /** + * Module path. + *

+ * If not specified, the JDKs jmods directory will be used, if it exists. If specified, but it does not contain the + * {@code java.base} module, the JDKs jmods directory will be added, if it exists. + * + * @param path the module path + * @return this map of options + */ + public JpackageOptions modulePath(String path) { + put("--module-path", path); + return this; + } + + /** + * List of module paths. + *

+ * Each path is either a directory of modules or the path to a modular jar. + *

+ * Each path is absolute or relative to the current directory. + * + * @param path one or more path + * @return this map of options + */ + public JpackageOptions modulePath(String... path) { + put("--module-path", String.join(",", path)); + return this; + } + + /** + * Name of the application and/or package. + * + * @param name the name + * @return this map of options + */ + public JpackageOptions name(String name) { + put("--name", name); + return this; + } + + /** + * Path to override jpackage resources. + *

+ * Icons, template files, and other resources of jpackage can be over-ridden by adding replacement resources to + * this directory. + * + * @param path absolute path or relative to the current directory + * @return this map of options + */ + public JpackageOptions resourceDir(String path) { + put("--resource-dir", path); + return this; + } + + /** + * Path of the predefined runtime image that will be copied into the application image. + *

+ * If not specified, jpackage will run jlink to create the runtime image using options: + * {@link JlinkOptions#stripNativeCommands(boolean) stripNativeCommands} + * {@link JlinkOptions#stripDebug(boolean) stripDebug} {@link JlinkOptions#noManPages(boolean) noManPages} + * {@link JlinkOptions#noHeaderFiles(boolean) noHeaderFiles} + *

+ * Option is required when creating a runtime package. + * + * @param path absolute path or relative to the current directory + * @return this map of options + */ + public JpackageOptions runtimeImage(String path) { + put("--runtime-image", path); + return this; + } + + /** + * Strip debug information. + * + * @param stripDebug {@code true} to strip debug info, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions stripDebug(boolean stripDebug) { + if (stripDebug) { + put("--strip-debug", null); + } else { + remove("--strip-debug"); + } + return this; + } + + /** + * Path of a new or empty directory used to create temporary files. + *

+ * If specified, the temp dir will not be removed upon the task completion and must be removed manually. + *

+ * If not specified, a temporary directory will be created and removed upon the task completion. + * + * @param path absolute path or relative to the current directory + * @return this map of options + */ + public JpackageOptions temp(String path) { + put("--temp", path); + return this; + } + + /** + * The type of package to create. + * + * @param type the package type + * @return this map of options + */ + public JpackageOptions type(PackageType type) { + put("--type", type.type); + return this; + } + + /** + * Vendor of the application. + * + * @param vendor the vendor + * @return this map of options + */ + public JpackageOptions vendor(String vendor) { + put("--vendor", vendor); + return this; + } + + /** + * An identifier that uniquely identifies the application for macOS. + *

+ * Defaults to the main class name. + *

+ * May only use alphanumeric ({@code A-Z,a-z,0-9}), hyphen ({@code -}), and period ({@code .}) characters. + * + * @param packageIdentifier the package identifier + * @return this map of options + */ + public JpackageOptions macPackageIdentifier(String packageIdentifier) { + put("--mac-package-identifier", packageIdentifier); + return this; + } + + /** + * When signing the application package, this value is prefixed to all components that need to be signed that don't + * have an existing package identifier. + * + * @param packageSigningPrefix the signing prefix + * @return this map of options + */ + public JpackageOptions macPackageSigningPrefix(String packageSigningPrefix) { + put("--mac-package-signing-prefix", packageSigningPrefix); + return this; + } + + /** + * When signing the application package, this value is prefixed to all components that need to be signed that don't + * have an existing package identifier. + * + * @param prefix the prefix + * @return this map of options + */ + public JpackageOptions macSign(String prefix) { + put("--mac-sign", prefix); + return this; + } + + /** + * Name of the keychain to search for the signing identity. + *

+ * If not specified, the standard keychains are used. + * + * @param keychain the keychain name + * @return this map of options + */ + public JpackageOptions macSigningKeychain(String keychain) { + put("--mac-signing-keychain", keychain); + return this; + } + + /** + * Team or user name portion in Apple signing identities. + * + * @param username the username + * @return this map of options + */ + public JpackageOptions macSigningKeyUserName(String username) { + put("--mac-signing-key-user-name", username); + return this; + } + + /** + * String used to construct {@code LSApplicationCategoryType} in application plist. + *

+ * The default value is {@code utilities}. + * + * @param appCategory the category + * @return this map of options + */ + public JpackageOptions macAppCategory(String appCategory) { + put("--mac-app-category", appCategory); + return this; + } + + /** + * Path to file containing entitlements to use when signing executables and libraries in the bundle. + * + * @param path the fie path + * @return this map of options + */ + public JpackageOptions macEntitlements(String path) { + put("--mac-entitlements", path); + return this; + } + + /** + * Indicates that the jpackage output is intended for the Mac App Store. + * + * @param appStore {@code true} if intended for the Mac App Store, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions macAppStore(boolean appStore) { + if (appStore) { + put("--mac-app-store", null); + } else { + remove("--mac-app-store"); + } + return this; + } + + /** + * Name of the application as it appears in the Menu Bar + *

+ * This can be different from the application name. + *

+ * This name must be less than 16 characters long and be suitable for displaying in the menu bar and the application + * Info window. + *

+ * Defaults to the application name. + * + * @param name the package name + * @return this map of options + */ + public JpackageOptions macPackageName(String name) { + put("--mac-package-name", name); + return this; + } + + /** + * Enables verbose output. + * + * @param verbose {@code true} to enable verbose tracing, {@code false} otherwise. + * @return this map of options + */ + public JpackageOptions verbose(boolean verbose) { + if (verbose) { + put("--verbose", null); + } else { + remove("--verbose"); + } + return this; + } + + /** + * Adds a dialog to enable the user to choose a directory in which the product is installed.. + * + * @param winDirChooser {@code true} to let the user choose a directory, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions winDirChooser(boolean winDirChooser) { + if (winDirChooser) { + put("--win-dir-chooser", null); + } else { + remove("--win-dir-chooser"); + } + return this; + } + + /** + * URL where user can obtain further information or technical support. + * + * @param helpUrl the help URL + * @return this map of options + */ + public JpackageOptions winHelpUrl(String helpUrl) { + put("--win-help-url", helpUrl); + return this; + } + + /** + * Request to add a Start Menu shortcut for this application. + * + * @param winMenu {@code true} to add a start menu shortcut, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions winMenu(boolean winMenu) { + if (winMenu) { + put("--win-menu", null); + } else { + remove("--win-menu"); + } + return this; + } + + /** + * Start Menu group this application is placed in. + * + * @param menuGroup the menu group + * @return this map of options + */ + public JpackageOptions winMenuGroupM(String menuGroup) { + put("--win-menu-group", menuGroup); + return this; + } + + /** + * Request to perform an install on a per-user basis. + * + * @param winPerUserInstall {@code true} for per-user install, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions winPerUserInstall(boolean winPerUserInstall) { + if (winPerUserInstall) { + put("--win-per-user-install", null); + } else { + remove("--win-per-user-install"); + } + return this; + } + + /** + * Request to create a desktop shortcut for this application. + * + * @param winShortcut {@code true} to create a shortcut, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions winShortcut(boolean winShortcut) { + if (winShortcut) { + put("--win-shortcut", null); + } else { + remove("--win-shortcut"); + } + return this; + } + + /** + * Adds a dialog to enable the user to choose if shortcuts will be created by installer. + * + * @param shortcutPrompt {@code true} to add a prompt; {@code false} otherwise + * @return this map of options + */ + public JpackageOptions winShortcutPrompt(boolean shortcutPrompt) { + if (shortcutPrompt) { + put("--win-shortcut-prompt", null); + } else { + remove("--win-shortcut-prompt"); + } + return this; + } + + /** + * URL of available application update information. + * + * @param url the URL + * @return this map of options + */ + public JpackageOptions winUpdateUrl(String url) { + put("--win-update-url", url); + return this; + } + + /** + * UUID associated with upgrades for this package. + * + * @param uuid the uuid + * @return this map of options + */ + public JpackageOptions winUpgradeUuid(String uuid) { + put("--win-upgrade-uuid", uuid); + return this; + } + + /** + * Creates a console launcher for the application, should be specified for application which requires console + * interactions. + * + * @param winConsole {@code true} to create a console launcher, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions winConsole(boolean winConsole) { + if (winConsole) { + put("--win-console", null); + } else { + remove("--win-console"); + } + return this; + } + + /** + * Include all the referenced content in the dmg. + * + * @param additionalContent one or more path + * @return this map of options + */ + public JpackageOptions macDmgContent(String... additionalContent) { + put("--mac-dmg-content", String.join(",", additionalContent)); + return this; + } + + /** + * The package types. + */ + public enum PackageType { + APP_IMAGE("app_image"), + DEB("deb"), + DMG("dmg"), + EXE("exe"), + MSI("msi"), + PKG("pkg"), + RPM("rpm"); + + final String type; + + PackageType(String type) { + this.type = type; + } + } + + /** + * Name of launcher, and a path to a Properties file that contains a list of key, value pairs/ + *

+ * The keys {@code module}, {@code main-jar}, {@code main-class}, {@code description}, + * {@code arguments}, {@code java-options}, {@code app-version}, {@code icon}, + * {@code launcher-as-service}, {@code win-console}, {@code win-shortcut}, {@code win-menu}, + * {@code linux-app-category}, and {@code linux-shortcut} can be used. + *

+ * These options are added to, or used to overwrite, the original command line options to build an additional + * alternative launcher. + * + * @param name the name + * @param path absolute path or relative to the current directory + */ + public record Launcher(String name, String path) { + } +} diff --git a/src/main/java/rife/bld/operations/ZipCompression.java b/src/main/java/rife/bld/operations/ZipCompression.java new file mode 100644 index 0000000..4d5722a --- /dev/null +++ b/src/main/java/rife/bld/operations/ZipCompression.java @@ -0,0 +1,30 @@ +/** + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ +package rife.bld.operations; + +/** + * The zip compression levels for jlink and jmod. + * + * @author Erik C. Thauvin + * @since 2.0.2 + */ +public enum ZipCompression { + ZIP_0("zip-0"), + ZIP_1("zip-1"), + ZIP_2("zip-2"), + ZIP_3("zip-3"), + ZIP_4("zip-4"), + ZIP_5("zip-5"), + ZIP_6("zip-6"), + ZIP_7("zip-7"), + ZIP_8("zip-8"), + ZIP_9("zip-9"); + + public final String level; + + ZipCompression(String level) { + this.level = level; + } +} diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java new file mode 100644 index 0000000..007ffd2 --- /dev/null +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -0,0 +1,26 @@ +/* + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ + +package rife.bld.operations; + +import org.junit.Test; +import rife.bld.operations.exceptions.ExitStatusException; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class TestJlinkOperation { + @Test + public void TestNoArguments() { + var jlink = new JlinkOperation(); + assertThrows(ExitStatusException.class, jlink::execute); + } + + @Test + public void TestVersion() { + var jlink = new JlinkOperation().toolArg("--version"); + assertDoesNotThrow(jlink::execute); + } +} diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java new file mode 100644 index 0000000..8767ecb --- /dev/null +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -0,0 +1,26 @@ +/* + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ + +package rife.bld.operations; + +import org.junit.Test; +import rife.bld.operations.exceptions.ExitStatusException; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class TestJmodOperation { + @Test + public void TestNoArguments() { + var jmod = new JmodOperation(); + assertThrows(ExitStatusException.class, jmod::execute); + } + + @Test + public void TestVersion() { + var jmod = new JmodOperation().operationMode(JmodOperation.OperationMode.DESCRIBE).toolArg("--version"); + assertDoesNotThrow(jmod::execute); + } +} diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java new file mode 100644 index 0000000..4850fc2 --- /dev/null +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -0,0 +1,56 @@ +/* + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ + +package rife.bld.operations; + +import org.junit.Test; +import rife.bld.operations.exceptions.ExitStatusException; + +import java.io.File; +import java.nio.file.Files; + +import static org.junit.jupiter.api.Assertions.*; + +public class TestJpackageOperation { + @Test + public void TestCreatePackage() throws Exception { + var tmpdir = Files.createTempDirectory("bld-jpackage-test").toFile(); + tmpdir.deleteOnExit(); + var options = new JpackageOptions() + .input("lib/bld") + .name("bld") + .mainJar("bld-wrapper.jar") + .javaOptions("--enable-preview") + .dest(tmpdir.getAbsolutePath()) + .verbose(true); + + var os = System.getProperty("os.name"); + if (os.startsWith("Windows")) { + options.type(JpackageOptions.PackageType.EXE); + } else if (os.startsWith("Linux")) { + options.type(JpackageOptions.PackageType.DEB); + } else if (os.startsWith("Mac")) { + options.type(JpackageOptions.PackageType.DMG); + } + + var jpackage = new JpackageOperation().jpackageOptions(options); + jpackage.execute(); + + var deb = new File(tmpdir, "bld_1.0-1_amd64.deb"); + assertTrue(deb.delete()); + } + + @Test + public void TestNoArguments() { + var jpackage = new JpackageOperation(); + assertThrows(ExitStatusException.class, jpackage::execute); + } + + @Test + public void TestVersion() { + var jpackage = new JpackageOperation().toolArg("--version"); + assertDoesNotThrow(jpackage::execute); + } +} From 683f5dfb3afa6bdf9524dd934096845554223bd7 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 1 Aug 2024 12:14:09 -0700 Subject: [PATCH 02/27] Fixed test imports --- src/test/java/rife/bld/operations/TestJlinkOperation.java | 6 +++--- src/test/java/rife/bld/operations/TestJmodOperation.java | 6 +++--- .../java/rife/bld/operations/TestJpackageOperation.java | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index 007ffd2..c46c9dc 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -5,7 +5,7 @@ package rife.bld.operations; -import org.junit.Test; +import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -13,13 +13,13 @@ import static org.junit.jupiter.api.Assertions.assertThrows; public class TestJlinkOperation { @Test - public void TestNoArguments() { + void testNoArguments() { var jlink = new JlinkOperation(); assertThrows(ExitStatusException.class, jlink::execute); } @Test - public void TestVersion() { + void testVersion() { var jlink = new JlinkOperation().toolArg("--version"); assertDoesNotThrow(jlink::execute); } diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index 8767ecb..61c1a39 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -5,7 +5,7 @@ package rife.bld.operations; -import org.junit.Test; +import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -13,13 +13,13 @@ import static org.junit.jupiter.api.Assertions.assertThrows; public class TestJmodOperation { @Test - public void TestNoArguments() { + void testNoArguments() { var jmod = new JmodOperation(); assertThrows(ExitStatusException.class, jmod::execute); } @Test - public void TestVersion() { + void testVersion() { var jmod = new JmodOperation().operationMode(JmodOperation.OperationMode.DESCRIBE).toolArg("--version"); assertDoesNotThrow(jmod::execute); } diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index 4850fc2..15c4e5d 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -5,7 +5,7 @@ package rife.bld.operations; -import org.junit.Test; +import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; import java.io.File; @@ -15,7 +15,7 @@ import static org.junit.jupiter.api.Assertions.*; public class TestJpackageOperation { @Test - public void TestCreatePackage() throws Exception { + void testCreatePackage() throws Exception { var tmpdir = Files.createTempDirectory("bld-jpackage-test").toFile(); tmpdir.deleteOnExit(); var options = new JpackageOptions() @@ -43,13 +43,13 @@ public class TestJpackageOperation { } @Test - public void TestNoArguments() { + void testNoArguments() { var jpackage = new JpackageOperation(); assertThrows(ExitStatusException.class, jpackage::execute); } @Test - public void TestVersion() { + void testVersion() { var jpackage = new JpackageOperation().toolArg("--version"); assertDoesNotThrow(jpackage::execute); } From 7fcbccd565a030c35cc2ec85deebf5af29e5bc02 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 1 Aug 2024 13:42:55 -0700 Subject: [PATCH 03/27] Install limbd0 on Ubuntu --- .github/workflows/bld.yml | 2 ++ .../bld/operations/TestJpackageOperation.java | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index abd8ea4..c5979fa 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -90,6 +90,8 @@ jobs: java-version: [ 17, 20, 21, 22 ] steps: + - name: Install libmd + run: apt-get update -qq && apt-get install -y libmd0 - name: Checkout source repository uses: actions/checkout@v4 with: diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index 15c4e5d..e91c648 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -8,7 +8,6 @@ package rife.bld.operations; import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; -import java.io.File; import java.nio.file.Files; import static org.junit.jupiter.api.Assertions.*; @@ -26,20 +25,22 @@ public class TestJpackageOperation { .dest(tmpdir.getAbsolutePath()) .verbose(true); - var os = System.getProperty("os.name"); - if (os.startsWith("Windows")) { - options.type(JpackageOptions.PackageType.EXE); - } else if (os.startsWith("Linux")) { + var os = System.getProperty("os.version"); + if (os.endsWith("MANJARO")) { options.type(JpackageOptions.PackageType.DEB); - } else if (os.startsWith("Mac")) { - options.type(JpackageOptions.PackageType.DMG); } var jpackage = new JpackageOperation().jpackageOptions(options); jpackage.execute(); - var deb = new File(tmpdir, "bld_1.0-1_amd64.deb"); - assertTrue(deb.delete()); + var files = tmpdir.listFiles(); + assertNotNull(files, "files should not be null"); + assertTrue(files.length > 0, "No files found"); + + for (var file : files) { + System.out.println(file.getName()); + file.deleteOnExit(); + } } @Test From 0aa93b708a7c652a2e6a020dde35ad06397636b1 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 1 Aug 2024 14:02:24 -0700 Subject: [PATCH 04/27] Install limbd0 on Ubuntu with sudo --- .github/workflows/bld.yml | 2 +- .../java/rife/bld/operations/TestJpackageOperation.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index c5979fa..0537759 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -91,7 +91,7 @@ jobs: steps: - name: Install libmd - run: apt-get update -qq && apt-get install -y libmd0 + run: sudo apt-get update -qq && sudo apt-get install -y libmd0 - name: Checkout source repository uses: actions/checkout@v4 with: diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index e91c648..b3ae927 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -7,6 +7,7 @@ package rife.bld.operations; import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; +import rife.tools.FileUtils; import java.nio.file.Files; @@ -37,10 +38,9 @@ public class TestJpackageOperation { assertNotNull(files, "files should not be null"); assertTrue(files.length > 0, "No files found"); - for (var file : files) { - System.out.println(file.getName()); - file.deleteOnExit(); - } + assertTrue(files[0].getName().matches("bld.*\\.[A-Za-z]{3}"), "Package not found"); + + FileUtils.deleteDirectory(tmpdir); } @Test From d69956cf910a3320940e0daf8a9e26cb6a86570d Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 1 Aug 2024 14:19:59 -0700 Subject: [PATCH 05/27] Revert install limbd0 on Ubuntu --- .github/workflows/bld.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index 0537759..abd8ea4 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -90,8 +90,6 @@ jobs: java-version: [ 17, 20, 21, 22 ] steps: - - name: Install libmd - run: sudo apt-get update -qq && sudo apt-get install -y libmd0 - name: Checkout source repository uses: actions/checkout@v4 with: From 0ad964ea4dccd4a309441975016413430af58fc2 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 2 Aug 2024 02:54:46 -0700 Subject: [PATCH 06/27] Cleaned up and improved tests --- .../AbstractToolProviderOperation.java | 73 ++- .../rife/bld/operations/JlinkOperation.java | 28 +- .../rife/bld/operations/JlinkOptions.java | 98 ++-- .../rife/bld/operations/JmodOperation.java | 52 +- .../java/rife/bld/operations/JmodOptions.java | 18 +- .../bld/operations/JpackageOperation.java | 2 +- .../rife/bld/operations/JpackageOptions.java | 444 ++++++++++-------- .../bld/operations/TestJlinkOperation.java | 66 ++- .../bld/operations/TestJmodOperation.java | 67 ++- .../bld/operations/TestJpackageOperation.java | 141 +++++- 10 files changed, 685 insertions(+), 304 deletions(-) diff --git a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java index 6113069..3513436 100644 --- a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java +++ b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java @@ -9,7 +9,6 @@ import rife.bld.operations.exceptions.ExitStatusException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.spi.ToolProvider; @@ -22,7 +21,7 @@ import java.util.spi.ToolProvider; */ public abstract class AbstractToolProviderOperation> extends AbstractOperation> { - private final Map toolArgs_ = new HashMap<>(); + private final List toolArgs_ = new ArrayList<>(); private final String toolName_; /** @@ -34,35 +33,6 @@ public abstract class AbstractToolProviderOperation argsToList(Map args) { - var list = new ArrayList(); - for (String arg : args.keySet()) { - var value = args.get(arg); - list.add(arg); - if (value != null && !value.isEmpty()) { - list.add(value); - } - } - return list; - } - - /** - * Adds tool command line argument. - * - * @param arg the argument to add - * @return this operation - */ - public T toolArg(String arg) { - toolArgs_.put(arg, null); - return (T) this; - } - /** * Add tool command line argument. * @@ -70,8 +40,12 @@ public abstract class AbstractToolProviderOperation args) { - toolArgs_.putAll(args); + @SuppressWarnings({"unchecked", "UnusedReturnValue"}) + protected T addArgs(Map args) { + args.forEach(this::addArg); return (T) this; } /** - * Clears the tool command line arguments. + * Adds tool command line arguments. * + * @param args the argument to add * @return this operation */ - protected T clearToolArguments() { - toolArgs_.clear(); + @SuppressWarnings({"unchecked", "UnusedReturnValue"}) + public T addArgs(List args) { + toolArgs_.addAll(args); + return (T) this; + } + + /** + * Adds tool command line arguments. + * + * @param arg one or more argument + * @return this operation + */ + @SuppressWarnings("unchecked") + public T addArgs(String... arg) { + addArgs(List.of(arg)); return (T) this; } @@ -105,17 +94,15 @@ public abstract class AbstractToolProviderOperation new IllegalStateException("No " + toolName_ + " tool found.")); - var argsList = argsToList(toolArgs_); - var stderr = new StringWriter(); var stdout = new StringWriter(); try (var err = new PrintWriter(stderr); var out = new PrintWriter(stdout)) { - var status = tool.run(out, err, argsList.toArray(new String[0])); + var status = tool.run(out, err, toolArgs_.toArray(new String[0])); out.flush(); err.flush(); if (status != 0) { - System.out.println(tool.name() + " " + String.join(" ", argsList)); + System.out.println(tool.name() + ' ' + String.join(" ", toolArgs_)); } var output = stdout.toString(); @@ -136,7 +123,7 @@ public abstract class AbstractToolProviderOperation toolArgs() { + public List toolArgs() { return toolArgs_; } } diff --git a/src/main/java/rife/bld/operations/JlinkOperation.java b/src/main/java/rife/bld/operations/JlinkOperation.java index c3d5d44..cb6ad87 100644 --- a/src/main/java/rife/bld/operations/JlinkOperation.java +++ b/src/main/java/rife/bld/operations/JlinkOperation.java @@ -5,6 +5,8 @@ package rife.bld.operations; +import java.util.ArrayList; +import java.util.List; import java.util.Map; /** @@ -15,14 +17,26 @@ import java.util.Map; */ public class JlinkOperation extends AbstractToolProviderOperation { private final JlinkOptions jlinkOptions_ = new JlinkOptions(); + private final List disabledPlugins_ = new ArrayList<>(); public JlinkOperation() { super("jlink"); } + /** + * Disable the plugin mentioned. + * + * @param plugin the plugin name + * @return this map of options + */ + public JlinkOperation disablePlugin(String... plugin) { + disabledPlugins_.addAll(List.of(plugin)); + return this; + } + @Override public void execute() throws Exception { - toolArgs(jlinkOptions_); + disabledPlugins_.forEach(plugin -> addArg("--disable-plugin", plugin)); super.execute(); } @@ -31,12 +45,22 @@ public class JlinkOperation extends AbstractToolProviderOperation * This is a modifiable list that can be retrieved and changed. * - * @return the list of jlink options + * @return the map of jlink options */ public JlinkOptions jlinkOptions() { return jlinkOptions_; } + /** + * List available plugins. + * + * @return this operation instance + */ + public JlinkOperation listPlugins() { + addArgs("--list-plugins"); + return this; + } + /** * Provides a list of options to provide to the jlink tool. *

diff --git a/src/main/java/rife/bld/operations/JlinkOptions.java b/src/main/java/rife/bld/operations/JlinkOptions.java index d9969b2..8c31f90 100644 --- a/src/main/java/rife/bld/operations/JlinkOptions.java +++ b/src/main/java/rife/bld/operations/JlinkOptions.java @@ -4,7 +4,9 @@ */ package rife.bld.operations; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; /** * Options for jlink tool. @@ -39,13 +41,24 @@ public class JlinkOptions extends HashMap { */ public JlinkOptions bindServices(boolean bindServices) { if (bindServices) { - put("--bind-services", null); + put("--bind-services"); } else { remove("--bind-services"); } return this; } + /** + * Read options from file. + * + * @param filename the filename + * @return this map of options + */ + public JlinkOptions filename(String filename) { + put("@" + filename); + return this; + } + /** * Compression to use in compressing resources. *

@@ -61,16 +74,6 @@ public class JlinkOptions extends HashMap { return this; } - /** - * Disable the plugin mentioned. - * - * @param plugin the plugin name - * @return this map of options - */ - public JlinkOptions disablePlugin(String plugin) { - put("--disable-plugin", plugin); - return this; - } /** * Byte order of generated jimage. @@ -85,17 +88,6 @@ public class JlinkOptions extends HashMap { return this; } - /** - * Read options from file. - * - * @param filename the filename - * @return this map of options - */ - public JlinkOptions filename(String filename) { - put("@" + filename, null); - return this; - } - /** * Suppress a fatal error when signed modular JARs are linked in the image. * @@ -104,7 +96,7 @@ public class JlinkOptions extends HashMap { */ public JlinkOptions ignoreSigningInformation(boolean ignoreSigningInformation) { if (ignoreSigningInformation) { - put("--ignore-signing-information", null); + put("--ignore-signing-information"); } else { remove("--ignore-signing-information"); } @@ -123,6 +115,21 @@ public class JlinkOptions extends HashMap { return this; } + /** + * Exclude include header files. + * + * @param noHeaderFiles {@code true} to exclude header files, {@code false} otherwise + * @return this map of options + */ + public JlinkOptions noHeaderFiles(boolean noHeaderFiles) { + if (noHeaderFiles) { + put("--no-header-files"); + } else { + remove("--no-header-files"); + } + return this; + } + /** * Add a launcher command of the given name for the module and the main class. * @@ -161,21 +168,6 @@ public class JlinkOptions extends HashMap { return this; } - /** - * Exclude include header files. - * - * @param noHeaderFiles {@code true} to exclude header files, {@code false} otherwise - * @return this map of options - */ - public JlinkOptions noHeaderFiles(boolean noHeaderFiles) { - if (noHeaderFiles) { - put("--no-header-files", null); - } else { - remove("--no-header-files"); - } - return this; - } - /** * Exclude man pages. * @@ -184,13 +176,23 @@ public class JlinkOptions extends HashMap { */ public JlinkOptions noManPages(boolean noManPages) { if (noManPages) { - put("--no-man-pages", null); + put("--no-man-pages"); } else { remove("--no-man-pages"); } return this; } + /** + * Associates {@code null} with the specified key in this map. If the map previously contained a mapping for the + * key, the old value is replaced. + * + * @param key key with which the specified value is to be associated + */ + public void put(String key) { + put(key, null); + } + /** * Location of output path. * @@ -221,7 +223,7 @@ public class JlinkOptions extends HashMap { */ public JlinkOptions stripDebug(boolean stripDebug) { if (stripDebug) { - put("--strip-debug", null); + put("--strip-debug"); } else { remove("--strip-debug"); } @@ -236,7 +238,7 @@ public class JlinkOptions extends HashMap { */ public JlinkOptions stripNativeCommands(boolean stripNativeCommands) { if (stripNativeCommands) { - put("--strip-native-commands", null); + put("--strip-native-commands"); } else { remove("--strip-native-commands"); } @@ -254,6 +256,17 @@ public class JlinkOptions extends HashMap { return this; } + public List toList() { + var list = new ArrayList(); + forEach((k, v) -> { + list.add(k); + if (v != null && !v.isEmpty()) { + list.add(v); + } + }); + return list; + } + /** * Enable verbose tracing * @@ -262,7 +275,7 @@ public class JlinkOptions extends HashMap { */ public JlinkOptions verbose(boolean verbose) { if (verbose) { - put("--verbose", null); + put("--verbose"); } else { remove("--verbose"); } @@ -281,4 +294,5 @@ public class JlinkOptions extends HashMap { this.byteOrder = byteOrder; } } + } diff --git a/src/main/java/rife/bld/operations/JmodOperation.java b/src/main/java/rife/bld/operations/JmodOperation.java index 071f703..362486e 100644 --- a/src/main/java/rife/bld/operations/JmodOperation.java +++ b/src/main/java/rife/bld/operations/JmodOperation.java @@ -17,6 +17,7 @@ import java.util.Map; */ public class JmodOperation extends AbstractToolProviderOperation { private final JmodOptions jmodOptions_ = new JmodOptions(); + private String jmodFile_; private OperationMode operationMode_; public JmodOperation() { @@ -28,18 +29,44 @@ public class JmodOperation extends AbstractToolProviderOperation if (operationMode_ == null) { System.err.println("Operation mode not set."); throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); + } else if (jmodFile_ == null) { + System.err.println("Jmod file not set."); + throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); } - toolArg(operationMode_.mode); - toolArgs(jmodOptions_); + addArgs(operationMode_.mode); + addArgs(jmodOptions_); + addArgs(jmodFile_); super.execute(); } + /** + * Retrieves the name of the JMOD file to create or from which to retrieve information. + * + * @return the JMOD file + */ + public String jmodFile() { + return jmodFile_; + } + + /** + * Specifies name of the JMOD file to create or from which to retrieve information. + *

+ * The JMOD file is required. + * + * @param file the JMOD file + * @return this operation instance + */ + public JmodOperation jmodFile(String file) { + jmodFile_ = file; + return this; + } + /** * Retrieves the list of options for the jmod tool. *

* This is a modifiable list that can be retrieved and changed. * - * @return the list of jmod options + * @return the map of jmod options */ public JmodOptions jmodOptions() { return jmodOptions_; @@ -59,7 +86,9 @@ public class JmodOperation extends AbstractToolProviderOperation } /** - * Provides the required {@link OperationMode operation mode}. + * Provides the {@link OperationMode operation mode}. + *

+ * The operation mode is required. * * @param mode the mode * @return this operation instance @@ -73,10 +102,25 @@ public class JmodOperation extends AbstractToolProviderOperation * The operation modes. */ public enum OperationMode { + /** + * Creates a new JMOD archive file. + */ CREATE("create"), + /** + * Prints the module details. + */ DESCRIBE("describe"), + /** + * Extracts all the files from the JMOD archive file. + */ EXTRACT("extract"), + /** + * Determines leaf modules and records the hashes of the dependencies that directly and indirectly require them. + */ HASH("hash"), + /** + * Prints the names of all the entries. + */ LIST("list"); final String mode; diff --git a/src/main/java/rife/bld/operations/JmodOptions.java b/src/main/java/rife/bld/operations/JmodOptions.java index acd7152..b24b9a0 100644 --- a/src/main/java/rife/bld/operations/JmodOptions.java +++ b/src/main/java/rife/bld/operations/JmodOptions.java @@ -94,7 +94,7 @@ public class JmodOptions extends HashMap { */ public JmodOptions doNotResolveByDefault(boolean doNotResolveByDefault) { if (doNotResolveByDefault) { - put("--do-not-resolve-by-default", null); + put("--do-not-resolve-by-default"); } else { remove("--do-not-resolve-by-default"); } @@ -109,7 +109,7 @@ public class JmodOptions extends HashMap { */ public JmodOptions dryRun(boolean dryRun) { if (dryRun) { - put("--dry-run", null); + put("--dry-run"); } else { remove("--dry-run"); } @@ -120,7 +120,7 @@ public class JmodOptions extends HashMap { * Exclude files matching the supplied pattern list. * * @param pattern one or more pattern - * @return the list of options + * @return the map of options */ public JmodOptions exclude(FilePattern... pattern) { var args = new ArrayList(); @@ -142,10 +142,20 @@ public class JmodOptions extends HashMap { * @return this map of options */ public JmodOptions filename(String filename) { - put("@" + filename, null); + put("@" + filename); return this; } + /** + * Associates {@code null} with the specified key in this map. If the map previously contained a mapping for the + * key, the old value is replaced. + * + * @param key key with which the specified value is to be associated + */ + public void put(String key) { + put(key, null); + } + /** * Compute and record hashes to tie a packaged module with modules matching the given regular expression pattern and * depending upon it directly or indirectly. The hashes are recorded in the JMOD file being created, or a JMOD file diff --git a/src/main/java/rife/bld/operations/JpackageOperation.java b/src/main/java/rife/bld/operations/JpackageOperation.java index 5fbdf0b..ee44928 100644 --- a/src/main/java/rife/bld/operations/JpackageOperation.java +++ b/src/main/java/rife/bld/operations/JpackageOperation.java @@ -22,7 +22,7 @@ public class JpackageOperation extends AbstractToolProviderOperation { return this; } + /** + * Read options and/or mode from a file. + * + * @param filename the filename + * @return this map of options + */ + public JpackageOptions filename(String filename) { + put("@" + filename); + return this; + } + /** * List of application launchers. *

@@ -68,17 +79,6 @@ public class JpackageOptions extends HashMap { return this; } - /** - * Options to pass to the Java runtime. - * - * @param options the options - * @return this map of options - */ - public JpackageOptions javaOptions(String... options) { - put("--java-options", String.join(" ", options)); - return this; - } - /** * Location of the predefined application image that is used to build an installable package. * @@ -160,13 +160,13 @@ public class JpackageOptions extends HashMap { } /** - * Read options and/or mode from a file. + * Options to pass to the Java runtime. * - * @param filename the filename + * @param options the options * @return this map of options */ - public JpackageOptions filename(String filename) { - put("@" + filename, null); + public JpackageOptions javaOptions(String... options) { + put("--java-options", String.join(" ", options)); return this; } @@ -205,6 +205,22 @@ public class JpackageOptions extends HashMap { return this; } + /** + * Request to create an installer that will register the main application launcher as a background service-type + * application. + * + * @param launcherAsService {@code true} to register the launcher as a service; {@code false} otherwise + * @return this map of options + */ + public JpackageOptions launcherAsService(boolean launcherAsService) { + if (launcherAsService) { + put("--launcher-as-service"); + } else { + remove("--launcher-as-service"); + } + return this; + } + /** * List of options to pass to jlink. *

@@ -216,22 +232,21 @@ public class JpackageOptions extends HashMap { * @return this map of options */ public JpackageOptions jlinkOptions(JlinkOptions options) { - put("--jlink-options", String.join(" ", AbstractToolProviderOperation.argsToList(options))); + put("--jlink-options", String.join(" ", options.toList())); return this; } /** - * Request to create an installer that will register the main application launcher as a background service-type - * application. + * Required packages or capabilities for the application. * - * @param launcherAsService {@code true} to register the launcher as a service; {@code false} otherwise + * @param packageDeps {@code true} if required, {@code false} otherwise * @return this map of options */ - public JpackageOptions launcherAsService(boolean launcherAsService) { - if (launcherAsService) { - put("--launcher-as-service", null); + public JpackageOptions linuxPackageDeps(boolean packageDeps) { + if (packageDeps) { + put("--linux-package-deps"); } else { - remove("--launcher-as-service"); + remove("--linux-package-deps"); } return this; } @@ -292,13 +307,17 @@ public class JpackageOptions extends HashMap { } /** - * Required packages or capabilities for the application. + * Creates a shortcut for the application. * - * @param packageDeps the package dependencies - * @return this list of operation + * @param shortcut {@code true| to create a shortcut, {@code false} otherwise + * @return this map of options */ - public JpackageOptions linuxPackageDeps(String packageDeps) { - put("--linux-package-deps", packageDeps); + public JpackageOptions linuxShortcut(boolean shortcut) { + if (shortcut) { + put("--linux-shortcut"); + } else { + remove("--linux-shortcut"); + } return this; } @@ -325,20 +344,176 @@ public class JpackageOptions extends HashMap { } /** - * Creates a shortcut for the application. + * String used to construct {@code LSApplicationCategoryType} in application plist. + *

+ * The default value is {@code utilities}. * - * @param shortcut {@code true| to create a shortcut, {@code false} otherwise + * @param appCategory the category * @return this map of options */ - public JpackageOptions linuxShortcut(boolean shortcut) { - if (shortcut) { - put("--linux-shortcut", null); + public JpackageOptions macAppCategory(String appCategory) { + put("--mac-app-category", appCategory); + return this; + } + + /** + * Identity used to sign application image. + *

+ * This value will be passed directly to {@code --sign} option of {@code codesign} tool. + *

+ * This option cannot be combined with {@link #macSigningKeyUserName(String) macSignKeyUserName}. + * + * @param identity the identity + * @return this map of options + */ + public JpackageOptions macAppImageSignIdentity(String identity) { + put("--mac-app-image-sign-identity", identity); + return this; + } + + /** + * Indicates that the jpackage output is intended for the Mac App Store. + * + * @param appStore {@code true} if intended for the Mac App Store, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions macAppStore(boolean appStore) { + if (appStore) { + put("--mac-app-store"); } else { - remove("--linux-shortcut"); + remove("--mac-app-store"); } return this; } + /** + * Include all the referenced content in the dmg. + * + * @param additionalContent one or more path + * @return this map of options + */ + public JpackageOptions macDmgContent(String... additionalContent) { + put("--mac-dmg-content", String.join(",", additionalContent)); + return this; + } + + /** + * Path to file containing entitlements to use when signing executables and libraries in the bundle. + * + * @param path the fie path + * @return this map of options + */ + public JpackageOptions macEntitlements(String path) { + put("--mac-entitlements", path); + return this; + } + + /** + * Identity used to sign "pkg" installer. + *

+ * This value will be passed directly to {@code --sign} option of {@code productbuild} tool. + *

+ * This option cannot be combined with {@link #macSigningKeyUserName(String) macSignKeyUserName}. + * + * @param identity the identity + * @return this map of options + */ + public JpackageOptions macInstallerSignIdentity(String identity) { + put("--mac-installer-sign-identity", identity); + return this; + } + + /** + * An identifier that uniquely identifies the application for macOS. + *

+ * Defaults to the main class name. + *

+ * May only use alphanumeric ({@code A-Z,a-z,0-9}), hyphen ({@code -}), and period ({@code .}) characters. + * + * @param packageIdentifier the package identifier + * @return this map of options + */ + public JpackageOptions macPackageIdentifier(String packageIdentifier) { + put("--mac-package-identifier", packageIdentifier); + return this; + } + + /** + * Name of the application as it appears in the Menu Bar + *

+ * This can be different from the application name. + *

+ * This name must be less than 16 characters long and be suitable for displaying in the menu bar and the application + * Info window. + *

+ * Defaults to the application name. + * + * @param name the package name + * @return this map of options + */ + public JpackageOptions macPackageName(String name) { + put("--mac-package-name", name); + return this; + } + + /** + * When signing the application package, this value is prefixed to all components that need to be signed that don't + * have an existing package identifier. + * + * @param prefix the signing prefix + * @return this map of options + */ + public JpackageOptions macPackageSigningPrefix(String prefix) { + put("--mac-package-signing-prefix", prefix); + return this; + } + + /** + * Request that the package or the predefined application image be signed. + * + * @param sign {@code true} to sign, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions macSign(boolean sign) { + if (sign) { + put("--mac-sign"); + } else { + remove("--mac-sign"); + } + return this; + } + + /** + * Team or user name portion in Apple signing identities. + *

+ * For direct control of the signing identity used to sign application images or installers use + * {@link #macAppImageSignIdentity(String) macAppImageSignIdentity} and/or + * {@link #macInstallerSignIdentity(String) macInstallerSignIdentity}. + *

+ * This option cannot be combined with {@link #macAppImageSignIdentity(String) macAppImageSignIdentity} or + * {@link #macInstallerSignIdentity(String) macInstallerSignIdentity}. + * + * @param username the username + * @return this map of options + */ + public JpackageOptions macSigningKeyUserName(String username) { + put("--mac-signing-key-user-name", username); + return this; + } + + /** + * Name of the keychain to search for the signing identity. + *

+ * If not specified, the standard keychains are used. + * + * @param keychain the keychain name + * @return this map of options + */ + public JpackageOptions macSigningKeychain(String keychain) { + put("--mac-signing-keychain", keychain); + return this; + } + /** * Qualified name of the application main class to execute. *

@@ -360,6 +535,7 @@ public class JpackageOptions extends HashMap { * @param jar the path relative to the input path * @return this map of options */ + @SuppressWarnings("JavadocDeclaration") public JpackageOptions mainJar(String jar) { put("--main-jar", jar); return this; @@ -368,14 +544,14 @@ public class JpackageOptions extends HashMap { /** * The main module and main class of the application. *

- * This module must be located on the {@link #modulePath(String) module path}. + * This module must be located on the {@link #modulePath(String...) module path}. *

* When this option is specified, the main module will be linked in the Java runtime image. *

* Either {@link #module(String, String) module} or {@link #mainJar(String) mainJar} option can be specified but not both. * * @param name the module name - * @return this list of operation + * @return this map of options */ public JpackageOptions module(String name) { put("--module", name); @@ -385,7 +561,7 @@ public class JpackageOptions extends HashMap { /** * The main module and main class of the application. *

- * This module must be located on the {@link #modulePath(String) module path}. + * This module must be located on the {@link #modulePath(String...) module path}. *

* When this option is specified, the main module will be linked in the Java runtime image. *

@@ -395,23 +571,20 @@ public class JpackageOptions extends HashMap { * @param mainClass the main class * @return this map of options */ + @SuppressWarnings("JavadocDeclaration") public JpackageOptions module(String name, String mainClass) { put("--module-name", name + "/" + mainClass); return this; } /** - * Module path. - *

- * If not specified, the JDKs jmods directory will be used, if it exists. If specified, but it does not contain the - * {@code java.base} module, the JDKs jmods directory will be added, if it exists. + * Associates {@code null} with the specified key in this map. If the map previously contained a mapping for the + * key, the old value is replaced. * - * @param path the module path - * @return this map of options + * @param key key with which the specified value is to be associated */ - public JpackageOptions modulePath(String path) { - put("--module-path", path); - return this; + public void put(String key) { + put(key, null); } /** @@ -480,7 +653,7 @@ public class JpackageOptions extends HashMap { */ public JpackageOptions stripDebug(boolean stripDebug) { if (stripDebug) { - put("--strip-debug", null); + put("--strip-debug"); } else { remove("--strip-debug"); } @@ -524,126 +697,6 @@ public class JpackageOptions extends HashMap { return this; } - /** - * An identifier that uniquely identifies the application for macOS. - *

- * Defaults to the main class name. - *

- * May only use alphanumeric ({@code A-Z,a-z,0-9}), hyphen ({@code -}), and period ({@code .}) characters. - * - * @param packageIdentifier the package identifier - * @return this map of options - */ - public JpackageOptions macPackageIdentifier(String packageIdentifier) { - put("--mac-package-identifier", packageIdentifier); - return this; - } - - /** - * When signing the application package, this value is prefixed to all components that need to be signed that don't - * have an existing package identifier. - * - * @param packageSigningPrefix the signing prefix - * @return this map of options - */ - public JpackageOptions macPackageSigningPrefix(String packageSigningPrefix) { - put("--mac-package-signing-prefix", packageSigningPrefix); - return this; - } - - /** - * When signing the application package, this value is prefixed to all components that need to be signed that don't - * have an existing package identifier. - * - * @param prefix the prefix - * @return this map of options - */ - public JpackageOptions macSign(String prefix) { - put("--mac-sign", prefix); - return this; - } - - /** - * Name of the keychain to search for the signing identity. - *

- * If not specified, the standard keychains are used. - * - * @param keychain the keychain name - * @return this map of options - */ - public JpackageOptions macSigningKeychain(String keychain) { - put("--mac-signing-keychain", keychain); - return this; - } - - /** - * Team or user name portion in Apple signing identities. - * - * @param username the username - * @return this map of options - */ - public JpackageOptions macSigningKeyUserName(String username) { - put("--mac-signing-key-user-name", username); - return this; - } - - /** - * String used to construct {@code LSApplicationCategoryType} in application plist. - *

- * The default value is {@code utilities}. - * - * @param appCategory the category - * @return this map of options - */ - public JpackageOptions macAppCategory(String appCategory) { - put("--mac-app-category", appCategory); - return this; - } - - /** - * Path to file containing entitlements to use when signing executables and libraries in the bundle. - * - * @param path the fie path - * @return this map of options - */ - public JpackageOptions macEntitlements(String path) { - put("--mac-entitlements", path); - return this; - } - - /** - * Indicates that the jpackage output is intended for the Mac App Store. - * - * @param appStore {@code true} if intended for the Mac App Store, {@code false} otherwise - * @return this map of options - */ - public JpackageOptions macAppStore(boolean appStore) { - if (appStore) { - put("--mac-app-store", null); - } else { - remove("--mac-app-store"); - } - return this; - } - - /** - * Name of the application as it appears in the Menu Bar - *

- * This can be different from the application name. - *

- * This name must be less than 16 characters long and be suitable for displaying in the menu bar and the application - * Info window. - *

- * Defaults to the application name. - * - * @param name the package name - * @return this map of options - */ - public JpackageOptions macPackageName(String name) { - put("--mac-package-name", name); - return this; - } - /** * Enables verbose output. * @@ -652,13 +705,29 @@ public class JpackageOptions extends HashMap { */ public JpackageOptions verbose(boolean verbose) { if (verbose) { - put("--verbose", null); + put("--verbose"); } else { remove("--verbose"); } return this; } + /** + * Creates a console launcher for the application, should be specified for application which requires console + * interactions. + * + * @param winConsole {@code true} to create a console launcher, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions winConsole(boolean winConsole) { + if (winConsole) { + put("--win-console"); + } else { + remove("--win-console"); + } + return this; + } + /** * Adds a dialog to enable the user to choose a directory in which the product is installed.. * @@ -667,7 +736,7 @@ public class JpackageOptions extends HashMap { */ public JpackageOptions winDirChooser(boolean winDirChooser) { if (winDirChooser) { - put("--win-dir-chooser", null); + put("--win-dir-chooser"); } else { remove("--win-dir-chooser"); } @@ -693,7 +762,7 @@ public class JpackageOptions extends HashMap { */ public JpackageOptions winMenu(boolean winMenu) { if (winMenu) { - put("--win-menu", null); + put("--win-menu"); } else { remove("--win-menu"); } @@ -706,7 +775,7 @@ public class JpackageOptions extends HashMap { * @param menuGroup the menu group * @return this map of options */ - public JpackageOptions winMenuGroupM(String menuGroup) { + public JpackageOptions winMenuGroup(String menuGroup) { put("--win-menu-group", menuGroup); return this; } @@ -719,7 +788,7 @@ public class JpackageOptions extends HashMap { */ public JpackageOptions winPerUserInstall(boolean winPerUserInstall) { if (winPerUserInstall) { - put("--win-per-user-install", null); + put("--win-per-user-install"); } else { remove("--win-per-user-install"); } @@ -734,7 +803,7 @@ public class JpackageOptions extends HashMap { */ public JpackageOptions winShortcut(boolean winShortcut) { if (winShortcut) { - put("--win-shortcut", null); + put("--win-shortcut"); } else { remove("--win-shortcut"); } @@ -749,7 +818,7 @@ public class JpackageOptions extends HashMap { */ public JpackageOptions winShortcutPrompt(boolean shortcutPrompt) { if (shortcutPrompt) { - put("--win-shortcut-prompt", null); + put("--win-shortcut-prompt"); } else { remove("--win-shortcut-prompt"); } @@ -778,33 +847,6 @@ public class JpackageOptions extends HashMap { return this; } - /** - * Creates a console launcher for the application, should be specified for application which requires console - * interactions. - * - * @param winConsole {@code true} to create a console launcher, {@code false} otherwise - * @return this map of options - */ - public JpackageOptions winConsole(boolean winConsole) { - if (winConsole) { - put("--win-console", null); - } else { - remove("--win-console"); - } - return this; - } - - /** - * Include all the referenced content in the dmg. - * - * @param additionalContent one or more path - * @return this map of options - */ - public JpackageOptions macDmgContent(String... additionalContent) { - put("--mac-dmg-content", String.join(",", additionalContent)); - return this; - } - /** * The package types. */ diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index c46c9dc..7ab28db 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -8,8 +8,10 @@ package rife.bld.operations; import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; +import java.util.HashMap; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; public class TestJlinkOperation { @Test @@ -18,9 +20,67 @@ public class TestJlinkOperation { assertThrows(ExitStatusException.class, jlink::execute); } + @Test + void testDisablePlugin() { + var jlink = new JlinkOperation() + .disablePlugin("vm") + .disablePlugin("system-modules") + .listPlugins(); + assertDoesNotThrow(jlink::execute); + + assertTrue(jlink.toolArgs().containsAll(List.of("vm", "system-modules"))); + } + + @Test + void testOptions() { + var args = new HashMap(); + args.put("--add-modules", "module-1,module-2"); + args.put("--bind-services", null); + args.put("--compress", "zip-6"); + args.put("--endian", "big"); + args.put("--ignore-signing-information", null); + args.put("--launcher", "name=module/mainclass"); + args.put("--limit-modules", "module-1,module-2"); + args.put("--module-path", "module-path"); + args.put("--no-header-files", null); + args.put("--no-man-pages", null); + args.put("--output", "output"); + args.put("--save-opts", "save-opts"); + args.put("--strip-debug", null); + args.put("--suggest-providers", "provider-1,provider-2"); + args.put("--verbose", null); + + var options = new JlinkOptions() + .addModules(args.get("--add-modules").split(",")) + .bindServices(true) + .compress(ZipCompression.ZIP_6) + .endian(JlinkOptions.Endian.BIG) + .ignoreSigningInformation(true) + .launcher("name", "module", "mainclass") + .limitModule(args.get("--limit-modules").split(",")) + .modulePath(args.get("--module-path")) + .noHeaderFiles(true) + .noManPages(true) + .output(args.get("--output")) + .saveOpts(args.get("--save-opts")) + .stripDebug(true) + .suggestProviders(args.get("--suggest-providers").split(",")) + .verbose(true); + + assertEquals(options.size(), args.size(), "Wrong number of arguments"); + + for (var arg : args.entrySet()) { + assertTrue(options.containsKey(arg.getKey()), arg.getValue() + " not found"); + assertEquals(arg.getValue(), options.get(arg.getKey()), arg.getKey()); + } + + options.launcher("name-2", "module-2"); + assertEquals("name-2=module-2", options.get("--launcher"), "incorrect launcher"); + } + @Test void testVersion() { - var jlink = new JlinkOperation().toolArg("--version"); + var jlink = new JlinkOperation().addArgs("--version"); assertDoesNotThrow(jlink::execute); } } diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index 61c1a39..47ecf54 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -8,8 +8,11 @@ package rife.bld.operations; import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.*; public class TestJmodOperation { @Test @@ -18,9 +21,67 @@ public class TestJmodOperation { assertThrows(ExitStatusException.class, jmod::execute); } + @Test + void testOptions() { + var args = new HashMap(); + args.put("--class-path", "classpath"); + args.put("--cmds", "cmds"); + args.put("--compress", "zip-5"); + args.put("--config", "config"); + args.put("--date", "1997-08-29T09:14:00Z"); + args.put("--dir", "dir"); + args.put("--do-not-resolve-by-default", null); + args.put("--dry-run", null); + args.put("--exclude", "glob:glob,regex:regex"); + args.put("--hash-modules", "regex"); + args.put("--header-files", "header-files"); + args.put("--legal-notices", "legal-notices"); + args.put("--libs", "libs"); + args.put("--main-class", "main-class"); + args.put("--man-pages", "man-pages"); + args.put("--module-path", "module-path"); + args.put("--module-version", "module-version"); + args.put("--target-platform", "target-platform"); + args.put("--warn-if-resolved", "deprecated"); + args.put("@filename", null); + + var options = new JmodOptions() + .classpath(args.get("--class-path")) + .cmds(args.get("--cmds")) + .compress(ZipCompression.ZIP_5) + .config(args.get("--config")) + .date(ZonedDateTime.of(1997, 8, 29, 2, 14, 0, 0, ZoneId.of("America/Los_Angeles"))) + .dir(args.get("--dir")) + .doNotResolveByDefault(true) + .dryRun(true) + .exclude(new JmodOptions.FilePattern(JmodOptions.FilePatternType.GLOB, "glob"), + new JmodOptions.FilePattern(JmodOptions.FilePatternType.REGEX, "regex")) + .filename("filename") + .hashModules(args.get("--hash-modules")) + .headerFiles(args.get("--header-files")) + .legalNotices(args.get("--legal-notices")) + .libs(args.get("--libs")) + .mainClass(args.get("--main-class")) + .manPages(args.get("--man-pages")) + .modulePath(args.get("--module-path")) + .moduleVersion(args.get("--module-version")) + .targetPlatform(args.get("--target-platform")) + .warnIfResolved(JmodOptions.ResolvedReason.DEPRECATED); + + assertEquals(options.size(), args.size(), "Wrong number of arguments"); + + for (var arg : args.entrySet()) { + assertTrue(options.containsKey(arg.getKey()), arg.getValue() + " not found"); + assertEquals(arg.getValue(), options.get(arg.getKey()), arg.getKey()); + } + } + @Test void testVersion() { - var jmod = new JmodOperation().operationMode(JmodOperation.OperationMode.DESCRIBE).toolArg("--version"); + var jmod = new JmodOperation() + .operationMode(JmodOperation.OperationMode.DESCRIBE) + .jmodFile("foo") + .addArgs("--version"); assertDoesNotThrow(jmod::execute); } } diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index b3ae927..53bad8f 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -10,6 +10,7 @@ import rife.bld.operations.exceptions.ExitStatusException; import rife.tools.FileUtils; import java.nio.file.Files; +import java.util.HashMap; import static org.junit.jupiter.api.Assertions.*; @@ -18,6 +19,7 @@ public class TestJpackageOperation { void testCreatePackage() throws Exception { var tmpdir = Files.createTempDirectory("bld-jpackage-test").toFile(); tmpdir.deleteOnExit(); + var options = new JpackageOptions() .input("lib/bld") .name("bld") @@ -49,9 +51,146 @@ public class TestJpackageOperation { assertThrows(ExitStatusException.class, jpackage::execute); } + @Test + void testOptions() { + var args = new HashMap(); + args.put("--about-url", "about-url"); + args.put("--add-launcher", "name=path"); + args.put("--add-modules", "modules-1,modules-2"); + args.put("--app-content", "content-1,content-2"); + args.put("--app-image", "app-image"); + args.put("--app-version", "app-version"); + args.put("--arguments", "argument1 argument2"); + args.put("--copyright", "copyright"); + args.put("--description", "description"); + args.put("--dest", "dest"); + args.put("--file-associations", "file-associations"); + args.put("--icon", "icon"); + args.put("--input", "input"); + args.put("--install-dir", "install-dir"); + args.put("--java-options", "java-options"); + args.put("--jlink-options", "--strip-debug --add-modules module-1,module-2"); + args.put("--launcher-as-service", null); + args.put("--license-file", "license-file"); + args.put("--linux-app-category", "linux-app-category"); + args.put("--linux-app-release", "linux-app-release"); + args.put("--linux-deb-maintainer", "linux-deb-maintainer"); + args.put("--linux-menu-group", "linux-menu-group"); + args.put("--linux-package-deps", null); + args.put("--linux-package-name", "linux-package-name"); + args.put("--linux-rpm-license-type", "linux-rpm-license-type"); + args.put("--linux-shortcut", null); + args.put("--mac-app-category", "mac-app-category"); + args.put("--mac-app-image-sign-identity", "mac-app-image-sign-identity"); + args.put("--mac-app-store", null); + args.put("--mac-dmg-content", "mac-dmg-content"); + args.put("--mac-entitlements", "mac-entitlements"); + args.put("--mac-installer-sign-identity", "mac-installer-sign-identity"); + args.put("--mac-package-identifier", "mac-package-identifier"); + args.put("--mac-package-name", "mac-package-name"); + args.put("--mac-package-signing-prefix", "mac-package-signing-prefix"); + args.put("--mac-sign", null); + args.put("--mac-signing-key-user-name", "mac-signing-key-user-name"); + args.put("--mac-signing-keychain", "mac-signing-keychain"); + args.put("--main-class", "main-class"); + args.put("--main-jar", "main-jar"); + args.put("--module", "module"); + args.put("--module-path", "module-path-1,module-path-2"); + args.put("--name", "name"); + args.put("--resource-dir", "resource-dir"); + args.put("--runtime-image", "runtime-image"); + args.put("--strip-debug", null); + args.put("--temp", "temp"); + args.put("--type", "exe"); + args.put("--vendor", "vendor"); + args.put("--verbose", null); + args.put("--win-console", null); + args.put("--win-dir-chooser", null); + args.put("--win-help-url", "win-help-url"); + args.put("--win-menu", null); + args.put("--win-menu-group", "win-menu-group"); + args.put("--win-per-user-install", null); + args.put("--win-shortcut", null); + args.put("--win-shortcut-prompt", null); + args.put("--win-update-url", "win-update-url"); + args.put("--win-upgrade-uuid", "win-upgrade-uuid"); + args.put("@filename", null); + + var options = new JpackageOptions() + .aboutUrl(args.get("--about-url")) + .addLauncher(new JpackageOptions.Launcher("name", "path")) + .addModules(args.get("--add-modules").split(",")) + .appContent(args.get("--app-content").split(",")) + .appImage(args.get("--app-image")) + .appVersion(args.get("--app-version")) + .arguments(args.get("--arguments").split(" ")) + .copyright(args.get("--copyright")) + .description(args.get("--description")) + .dest(args.get("--dest")) + .fileAssociations(args.get("--file-associations").split(",")) + .icon(args.get("--icon")) + .input(args.get("--input")) + .installDir(args.get("--install-dir")) + .javaOptions(args.get("--java-options").split(",")) + .jlinkOptions(new JlinkOptions().stripDebug(true).addModules("module-1", "module-2")) + .launcherAsService(true) + .licenseFile(args.get("--license-file")) + .linuxAppCategory(args.get("--linux-app-category")) + .linuxAppRelease(args.get("--linux-app-release")) + .linuxDebMaintainer(args.get("--linux-deb-maintainer")) + .linuxMenuGroup(args.get("--linux-menu-group")) + .linuxPackageDeps(true) + .linuxPackageName(args.get("--linux-package-name")) + .linuxRpmLicenseType(args.get("--linux-rpm-license-type")) + .linuxShortcut(true) + .macAppCategory(args.get("--mac-app-category")) + .macAppImageSignIdentity(args.get("--mac-app-image-sign-identity")) + .macAppStore(true) + .macDmgContent(args.get("--mac-dmg-content")) + .macEntitlements(args.get("--mac-entitlements")) + .macInstallerSignIdentity(args.get("--mac-installer-sign-identity")) + .macPackageIdentifier(args.get("--mac-package-identifier")) + .macPackageName(args.get("--mac-package-name")) + .macPackageSigningPrefix(args.get("--mac-package-signing-prefix")) + .macSign(true) + .macSigningKeyUserName(args.get("--mac-signing-key-user-name")) + .macSigningKeychain(args.get("--mac-signing-keychain")) + .mainClass(args.get("--main-class")) + .mainJar(args.get("--main-jar")) + .module(args.get("--module")) + .modulePath(args.get("--module-path").split(",")) + .name(args.get("--name")) + .resourceDir(args.get("--resource-dir")) + .runtimeImage(args.get("--runtime-image")) + .stripDebug(true) + .temp(args.get("--temp")) + .type(JpackageOptions.PackageType.EXE) + .vendor(args.get("--vendor")) + .verbose(true) + .winConsole(true) + .winDirChooser(true) + .winHelpUrl(args.get("--win-help-url")) + .winMenu(true) + .winMenuGroup(args.get("--win-menu-group")) + .winPerUserInstall(true) + .winShortcut(true) + .winShortcutPrompt(true) + .winUpdateUrl(args.get("--win-update-url")) + .winUpgradeUuid(args.get("--win-upgrade-uuid")) + .filename("filename"); + + assertEquals(options.size(), args.size(), "Wrong number of arguments"); + + for (var arg : args.entrySet()) { + assertTrue(options.containsKey(arg.getKey()), arg.getValue() + " not found"); + assertEquals(arg.getValue(), options.get(arg.getKey()), arg.getKey()); + } + + } + @Test void testVersion() { - var jpackage = new JpackageOperation().toolArg("--version"); + var jpackage = new JpackageOperation().addArgs("--version"); assertDoesNotThrow(jpackage::execute); } } From 002844861bd2039db62c56ec7237c46d3700bc1e Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 2 Aug 2024 14:23:22 -0700 Subject: [PATCH 07/27] Fixed handling of @filename in all tools --- .../rife/bld/operations/JlinkOperation.java | 63 +++++-- .../rife/bld/operations/JlinkOptions.java | 21 +-- .../rife/bld/operations/JmodOperation.java | 23 +++ .../java/rife/bld/operations/JmodOptions.java | 11 -- .../bld/operations/JpackageOperation.java | 23 +++ .../rife/bld/operations/JpackageOptions.java | 162 +++++++++--------- .../bld/operations/TestJlinkOperation.java | 52 ++++-- .../bld/operations/TestJmodOperation.java | 33 +++- .../bld/operations/TestJpackageOperation.java | 95 +++++----- src/test/resources/options_verbose.txt | 1 + src/test/resources/options_version.txt | 1 + 11 files changed, 297 insertions(+), 188 deletions(-) create mode 100644 src/test/resources/options_verbose.txt create mode 100644 src/test/resources/options_version.txt diff --git a/src/main/java/rife/bld/operations/JlinkOperation.java b/src/main/java/rife/bld/operations/JlinkOperation.java index cb6ad87..01130e7 100644 --- a/src/main/java/rife/bld/operations/JlinkOperation.java +++ b/src/main/java/rife/bld/operations/JlinkOperation.java @@ -5,9 +5,12 @@ package rife.bld.operations; +import java.io.File; +import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Scanner; /** * Create run-time images using the jlink tool. @@ -16,8 +19,9 @@ import java.util.Map; * @since 2.0.2 */ public class JlinkOperation extends AbstractToolProviderOperation { - private final JlinkOptions jlinkOptions_ = new JlinkOptions(); private final List disabledPlugins_ = new ArrayList<>(); + private final JlinkOptions jlinkOptions_ = new JlinkOptions(); + private final List options_ = new ArrayList<>(); public JlinkOperation() { super("jlink"); @@ -37,6 +41,8 @@ public class JlinkOperation extends AbstractToolProviderOperation addArg("--disable-plugin", plugin)); + addArgs(jlinkOptions_); + addArgs(parseOptions()); super.execute(); } @@ -51,16 +57,6 @@ public class JlinkOperation extends AbstractToolProviderOperation @@ -73,4 +69,49 @@ public class JlinkOperation extends AbstractToolProviderOperation options() { + return options_; + } + + // Shouldn't be needed, but for some reason jlink doesn't like @filename when called via ToolProvider + private List parseOptions() throws FileNotFoundException { + var list = new ArrayList(); + + for (var option : options_) { + try (var scanner = new Scanner(new File(option))) { + while (scanner.hasNext()) { + list.addAll(List.of(scanner.next().split(" "))); + } + } + } + + return list; + } } diff --git a/src/main/java/rife/bld/operations/JlinkOptions.java b/src/main/java/rife/bld/operations/JlinkOptions.java index 8c31f90..dd2dc71 100644 --- a/src/main/java/rife/bld/operations/JlinkOptions.java +++ b/src/main/java/rife/bld/operations/JlinkOptions.java @@ -15,9 +15,10 @@ import java.util.List; * @since 2.0.2 */ public class JlinkOptions extends HashMap { - /** + /**ranran * All Modules Path. */ + @SuppressWarnings("unused") public final static String ALL_MODULE_PATH = "ALL-MODULE-PATH"; /** @@ -48,22 +49,11 @@ public class JlinkOptions extends HashMap { return this; } - /** - * Read options from file. - * - * @param filename the filename - * @return this map of options - */ - public JlinkOptions filename(String filename) { - put("@" + filename); - return this; - } - /** * Compression to use in compressing resources. *

- * Where {@link ZipCompression#ZIP_0 ZIP_0} provides no compression and {@link ZipCompression#ZIP_9 ZIP_9} provides the - * best compression. + * Where {@link ZipCompression#ZIP_0 ZIP_0} provides no compression and {@link ZipCompression#ZIP_9 ZIP_9} provides + * the best compression. *

Default is {@link ZipCompression#ZIP_6 ZIP_6} * * @param compression the {@link ZipCompression compression} level @@ -110,6 +100,7 @@ public class JlinkOptions extends HashMap { * @param module the module * @return this map of options */ + @SuppressWarnings("UnusedReturnValue") public JlinkOptions launcher(String name, String module) { put("--launcher", name + "=" + module); return this; @@ -268,7 +259,7 @@ public class JlinkOptions extends HashMap { } /** - * Enable verbose tracing + * Enable verbose tracing. * * @param verbose {@code true} to enable verbose tracing, {@code false} otherwise. * @return this map of options diff --git a/src/main/java/rife/bld/operations/JmodOperation.java b/src/main/java/rife/bld/operations/JmodOperation.java index 362486e..58ed970 100644 --- a/src/main/java/rife/bld/operations/JmodOperation.java +++ b/src/main/java/rife/bld/operations/JmodOperation.java @@ -7,6 +7,8 @@ package rife.bld.operations; import rife.bld.operations.exceptions.ExitStatusException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; /** @@ -17,6 +19,7 @@ import java.util.Map; */ public class JmodOperation extends AbstractToolProviderOperation { private final JmodOptions jmodOptions_ = new JmodOptions(); + private final List options_ = new ArrayList<>(); private String jmodFile_; private OperationMode operationMode_; @@ -98,6 +101,26 @@ public class JmodOperation extends AbstractToolProviderOperation return this; } + /** + * Retrieves the list of files containing options or mode. + * + * @return the list of files + */ + public List options() { + return options_; + } + + /** + * Read options and/or mode from a file. + * + * @param filename one or more file + * @return this operation instance + */ + public JmodOperation options(String... filename) { + options_.addAll(List.of(filename)); + return this; + } + /** * The operation modes. */ diff --git a/src/main/java/rife/bld/operations/JmodOptions.java b/src/main/java/rife/bld/operations/JmodOptions.java index b24b9a0..ac36b20 100644 --- a/src/main/java/rife/bld/operations/JmodOptions.java +++ b/src/main/java/rife/bld/operations/JmodOptions.java @@ -135,17 +135,6 @@ public class JmodOptions extends HashMap { return this; } - /** - * Read options from the specified file. - * - * @param filename the filename - * @return this map of options - */ - public JmodOptions filename(String filename) { - put("@" + filename); - return this; - } - /** * Associates {@code null} with the specified key in this map. If the map previously contained a mapping for the * key, the old value is replaced. diff --git a/src/main/java/rife/bld/operations/JpackageOperation.java b/src/main/java/rife/bld/operations/JpackageOperation.java index ee44928..fabada1 100644 --- a/src/main/java/rife/bld/operations/JpackageOperation.java +++ b/src/main/java/rife/bld/operations/JpackageOperation.java @@ -5,6 +5,8 @@ package rife.bld.operations; +import java.util.ArrayList; +import java.util.List; import java.util.Map; /** @@ -15,6 +17,7 @@ import java.util.Map; */ public class JpackageOperation extends AbstractToolProviderOperation { private final JpackageOptions jpackageOptions_ = new JpackageOptions(); + private final List options_ = new ArrayList<>(); public JpackageOperation() { super("jpackage"); @@ -23,9 +26,29 @@ public class JpackageOperation extends AbstractToolProviderOperation '@' + opt).toList()); super.execute(); } + /** + * Retrieves the list of files containing options or mode. + * + * @return the list of files + */ + public List options(){ + return options_; + } + /** + * Read options and/or mode from a file. + * + * @param filename one or more file + * @return this operation instance + */ + public JpackageOperation options(String... filename) { + options_.addAll(List.of(filename)); + return this; + } + /** * Retrieves the list of options for the jpackage tool. *

diff --git a/src/main/java/rife/bld/operations/JpackageOptions.java b/src/main/java/rife/bld/operations/JpackageOptions.java index a0089d2..32321fe 100644 --- a/src/main/java/rife/bld/operations/JpackageOptions.java +++ b/src/main/java/rife/bld/operations/JpackageOptions.java @@ -25,17 +25,6 @@ public class JpackageOptions extends HashMap { return this; } - /** - * Read options and/or mode from a file. - * - * @param filename the filename - * @return this map of options - */ - public JpackageOptions filename(String filename) { - put("@" + filename); - return this; - } - /** * List of application launchers. *

@@ -135,7 +124,9 @@ public class JpackageOptions extends HashMap { } /** - * Path where generated output file is placed + * Path where generated output file is placed. + *

+ * Defaults to the current working directory. * * @param path absolute path or relative to the current directory * @return this map of options @@ -160,18 +151,7 @@ public class JpackageOptions extends HashMap { } /** - * Options to pass to the Java runtime. - * - * @param options the options - * @return this map of options - */ - public JpackageOptions javaOptions(String... options) { - put("--java-options", String.join(" ", options)); - return this; - } - - /** - * Path of the icon of the application package/ + * Path of the icon of the application package. * * @param path absolute path or relative to the current directory * @return this map of options @@ -195,7 +175,7 @@ public class JpackageOptions extends HashMap { } /** - * Absolute path of the installation directory of the application + * Absolute path of the installation directory of the application. * * @param path the absolute directory path * @return this map of options @@ -205,6 +185,32 @@ public class JpackageOptions extends HashMap { return this; } + /** + * Options to pass to the Java runtime. + * + * @param options the options + * @return this map of options + */ + public JpackageOptions javaOptions(String... options) { + put("--java-options", String.join(" ", options)); + return this; + } + + /** + * List of options to pass to jlink. + *

+ * If not specified, defaults to {@link JlinkOptions#stripNativeCommands(boolean) stripNativeCommands} + * {@link JlinkOptions#stripDebug(boolean) stripDebug} {@link JlinkOptions#noManPages(boolean) noManPages} + * {@link JlinkOptions#noHeaderFiles(boolean) noHeaderFiles}. + * + * @param options the {@link JlinkOptions} + * @return this map of options + */ + public JpackageOptions jlinkOptions(JlinkOptions options) { + put("--jlink-options", String.join(" ", options.toList())); + return this; + } + /** * Request to create an installer that will register the main application launcher as a background service-type * application. @@ -222,37 +228,7 @@ public class JpackageOptions extends HashMap { } /** - * List of options to pass to jlink. - *

- * If not specified, defaults to {@link JlinkOptions#stripNativeCommands(boolean) stripNativeCommands} - * {@link JlinkOptions#stripDebug(boolean) stripDebug} {@link JlinkOptions#noManPages(boolean) noManPages} - * {@link JlinkOptions#noHeaderFiles(boolean) noHeaderFiles}. - * - * @param options the {@link JlinkOptions} - * @return this map of options - */ - public JpackageOptions jlinkOptions(JlinkOptions options) { - put("--jlink-options", String.join(" ", options.toList())); - return this; - } - - /** - * Required packages or capabilities for the application. - * - * @param packageDeps {@code true} if required, {@code false} otherwise - * @return this map of options - */ - public JpackageOptions linuxPackageDeps(boolean packageDeps) { - if (packageDeps) { - put("--linux-package-deps"); - } else { - remove("--linux-package-deps"); - } - return this; - } - - /** - * Path to the license file + * Path to the license file. * * @param path absolute path or relative to the current directory * @return this map of options @@ -263,7 +239,7 @@ public class JpackageOptions extends HashMap { } /** - * Group value of the RPM {@code .spec} file or Section value of DEB control file + * Group value of the RPM {@code .spec} file or Section value of DEB control file. * * @param appCategory the application category * @return this map of options @@ -285,7 +261,7 @@ public class JpackageOptions extends HashMap { } /** - * Maintainer for .deb package. + * Maintainer for {@code .deb} package. * * @param maintainer the maintainer * @return this map of options @@ -307,16 +283,16 @@ public class JpackageOptions extends HashMap { } /** - * Creates a shortcut for the application. + * Required packages or capabilities for the application. * - * @param shortcut {@code true| to create a shortcut, {@code false} otherwise + * @param packageDeps {@code true} if required, {@code false} otherwise * @return this map of options */ - public JpackageOptions linuxShortcut(boolean shortcut) { - if (shortcut) { - put("--linux-shortcut"); + public JpackageOptions linuxPackageDeps(boolean packageDeps) { + if (packageDeps) { + put("--linux-package-deps"); } else { - remove("--linux-shortcut"); + remove("--linux-package-deps"); } return this; } @@ -333,7 +309,9 @@ public class JpackageOptions extends HashMap { } /** - * Type of the license ({@code License: } of the RPM .spec) + * Type of the license. + *

+ * {@code License: } of the RPM {@code .spec} * * @param licenseType the license type * @return this map of options @@ -343,6 +321,21 @@ public class JpackageOptions extends HashMap { return this; } + /** + * Creates a shortcut for the application. + * + * @param shortcut {@code true| to create a shortcut, {@code false} otherwise + * @return this map of options + */ + public JpackageOptions linuxShortcut(boolean shortcut) { + if (shortcut) { + put("--linux-shortcut"); + } else { + remove("--linux-shortcut"); + } + return this; + } + /** * String used to construct {@code LSApplicationCategoryType} in application plist. *

@@ -439,7 +432,7 @@ public class JpackageOptions extends HashMap { } /** - * Name of the application as it appears in the Menu Bar + * Name of the application as it appears in the Menu Bar. *

* This can be different from the application name. *

@@ -530,7 +523,8 @@ public class JpackageOptions extends HashMap { /** * The main JAR of the application; containing the main class. *

- * Either {@link #module(String, String) module} or {@link #mainJar(String) mainJar} option can be specified but not both. + * Either {@link #module(String, String) module} or {@link #mainJar(String) mainJar} option can be specified but + * not both. * * @param jar the path relative to the input path * @return this map of options @@ -548,7 +542,8 @@ public class JpackageOptions extends HashMap { *

* When this option is specified, the main module will be linked in the Java runtime image. *

- * Either {@link #module(String, String) module} or {@link #mainJar(String) mainJar} option can be specified but not both. + * Either {@link #module(String, String) module} or {@link #mainJar(String) mainJar} option can be specified but + * not both. * * @param name the module name * @return this map of options @@ -565,7 +560,8 @@ public class JpackageOptions extends HashMap { *

* When this option is specified, the main module will be linked in the Java runtime image. *

- * Either {@link #module(String, String) module} or {@link #mainJar(String) mainJar} option can be specified but not both. + * Either {@link #module(String, String) module} or {@link #mainJar(String) mainJar} option can be specified but + * not both. * * @param name the module name * @param mainClass the main class @@ -577,16 +573,6 @@ public class JpackageOptions extends HashMap { return this; } - /** - * Associates {@code null} with the specified key in this map. If the map previously contained a mapping for the - * key, the old value is replaced. - * - * @param key key with which the specified value is to be associated - */ - public void put(String key) { - put(key, null); - } - /** * List of module paths. *

@@ -598,7 +584,7 @@ public class JpackageOptions extends HashMap { * @return this map of options */ public JpackageOptions modulePath(String... path) { - put("--module-path", String.join(",", path)); + put("--module-path", String.join(":", path)); return this; } @@ -613,6 +599,16 @@ public class JpackageOptions extends HashMap { return this; } + /** + * Associates {@code null} with the specified key in this map. If the map previously contained a mapping for the + * key, the old value is replaced. + * + * @param key key with which the specified value is to be associated + */ + public void put(String key) { + put(key, null); + } + /** * Path to override jpackage resources. *

@@ -677,6 +673,8 @@ public class JpackageOptions extends HashMap { /** * The type of package to create. + *

+ * If this option is not specified a platform dependent default type will be created. * * @param type the package type * @return this map of options @@ -729,7 +727,7 @@ public class JpackageOptions extends HashMap { } /** - * Adds a dialog to enable the user to choose a directory in which the product is installed.. + * Adds a dialog to enable the user to choose a directory in which the product is installed. * * @param winDirChooser {@code true} to let the user choose a directory, {@code false} otherwise * @return this map of options @@ -867,7 +865,7 @@ public class JpackageOptions extends HashMap { } /** - * Name of launcher, and a path to a Properties file that contains a list of key, value pairs/ + * Name of launcher, and a path to a Properties file that contains a list of key, value pairs. *

* The keys {@code module}, {@code main-jar}, {@code main-class}, {@code description}, * {@code arguments}, {@code java-options}, {@code app-version}, {@code icon}, diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index 7ab28db..7845508 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -15,24 +15,7 @@ import static org.junit.jupiter.api.Assertions.*; public class TestJlinkOperation { @Test - void testNoArguments() { - var jlink = new JlinkOperation(); - assertThrows(ExitStatusException.class, jlink::execute); - } - - @Test - void testDisablePlugin() { - var jlink = new JlinkOperation() - .disablePlugin("vm") - .disablePlugin("system-modules") - .listPlugins(); - assertDoesNotThrow(jlink::execute); - - assertTrue(jlink.toolArgs().containsAll(List.of("vm", "system-modules"))); - } - - @Test - void testOptions() { + void testArguments() { var args = new HashMap(); args.put("--add-modules", "module-1,module-2"); args.put("--bind-services", null); @@ -78,9 +61,40 @@ public class TestJlinkOperation { assertEquals("name-2=module-2", options.get("--launcher"), "incorrect launcher"); } + @Test + void testDisablePlugin() { + var jlink = new JlinkOperation() + .disablePlugin("vm") + .disablePlugin("system-modules") + .listPlugins(); + assertDoesNotThrow(jlink::execute); + + assertTrue(jlink.toolArgs().containsAll(List.of("vm", "system-modules"))); + } + + @Test + void testHelp() { + var jlink = new JlinkOperation().addArgs("--help"); + assertDoesNotThrow(jlink::execute); + } + + @Test + void testNoArguments() { + var jlink = new JlinkOperation(); + assertTrue(jlink.jlinkOptions().isEmpty(), "jlink options not empty"); + assertTrue(jlink.options().isEmpty(), "options not empty"); + assertThrows(ExitStatusException.class, jlink::execute); + } + + @Test + void testOptions() { + var jlink = new JlinkOperation().options("src/test/resources/options_verbose.txt"); + assertDoesNotThrow(jlink::execute); + } + @Test void testVersion() { - var jlink = new JlinkOperation().addArgs("--version"); + var jlink = new JlinkOperation().addArgs("--verbose", "--version"); assertDoesNotThrow(jlink::execute); } } diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index 47ecf54..1dbbfaa 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -16,13 +16,7 @@ import static org.junit.jupiter.api.Assertions.*; public class TestJmodOperation { @Test - void testNoArguments() { - var jmod = new JmodOperation(); - assertThrows(ExitStatusException.class, jmod::execute); - } - - @Test - void testOptions() { + void testArguments() { var args = new HashMap(); args.put("--class-path", "classpath"); args.put("--cmds", "cmds"); @@ -43,7 +37,6 @@ public class TestJmodOperation { args.put("--module-version", "module-version"); args.put("--target-platform", "target-platform"); args.put("--warn-if-resolved", "deprecated"); - args.put("@filename", null); var options = new JmodOptions() .classpath(args.get("--class-path")) @@ -56,7 +49,6 @@ public class TestJmodOperation { .dryRun(true) .exclude(new JmodOptions.FilePattern(JmodOptions.FilePatternType.GLOB, "glob"), new JmodOptions.FilePattern(JmodOptions.FilePatternType.REGEX, "regex")) - .filename("filename") .hashModules(args.get("--hash-modules")) .headerFiles(args.get("--header-files")) .legalNotices(args.get("--legal-notices")) @@ -76,6 +68,29 @@ public class TestJmodOperation { } } + @Test + void testHelp() { + var jmod = new JmodOperation() + .operationMode(JmodOperation.OperationMode.HASH) + .jmodFile("foo") + .addArgs("--help-extra"); + assertDoesNotThrow(jmod::execute); + } + + @Test + void testNoArguments() { + var jmod = new JmodOperation(); + assertTrue(jmod.options().isEmpty(), "options not empty"); + assertTrue(jmod.jmodOptions().isEmpty(), "jmod options not empty"); + assertThrows(ExitStatusException.class, jmod::execute); + } + + @Test + void testOptions() { + var jpackage = new JpackageOperation().options("src/test/resources/options_version.txt"); + assertDoesNotThrow(jpackage::execute); + } + @Test void testVersion() { var jmod = new JmodOperation() diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index 53bad8f..8a1178b 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -15,44 +15,9 @@ import java.util.HashMap; import static org.junit.jupiter.api.Assertions.*; public class TestJpackageOperation { - @Test - void testCreatePackage() throws Exception { - var tmpdir = Files.createTempDirectory("bld-jpackage-test").toFile(); - tmpdir.deleteOnExit(); - - var options = new JpackageOptions() - .input("lib/bld") - .name("bld") - .mainJar("bld-wrapper.jar") - .javaOptions("--enable-preview") - .dest(tmpdir.getAbsolutePath()) - .verbose(true); - - var os = System.getProperty("os.version"); - if (os.endsWith("MANJARO")) { - options.type(JpackageOptions.PackageType.DEB); - } - - var jpackage = new JpackageOperation().jpackageOptions(options); - jpackage.execute(); - - var files = tmpdir.listFiles(); - assertNotNull(files, "files should not be null"); - assertTrue(files.length > 0, "No files found"); - - assertTrue(files[0].getName().matches("bld.*\\.[A-Za-z]{3}"), "Package not found"); - - FileUtils.deleteDirectory(tmpdir); - } @Test - void testNoArguments() { - var jpackage = new JpackageOperation(); - assertThrows(ExitStatusException.class, jpackage::execute); - } - - @Test - void testOptions() { + void testArguments() { var args = new HashMap(); args.put("--about-url", "about-url"); args.put("--add-launcher", "name=path"); @@ -95,7 +60,7 @@ public class TestJpackageOperation { args.put("--main-class", "main-class"); args.put("--main-jar", "main-jar"); args.put("--module", "module"); - args.put("--module-path", "module-path-1,module-path-2"); + args.put("--module-path", "module-path-1:module-path-2"); args.put("--name", "name"); args.put("--resource-dir", "resource-dir"); args.put("--runtime-image", "runtime-image"); @@ -114,7 +79,6 @@ public class TestJpackageOperation { args.put("--win-shortcut-prompt", null); args.put("--win-update-url", "win-update-url"); args.put("--win-upgrade-uuid", "win-upgrade-uuid"); - args.put("@filename", null); var options = new JpackageOptions() .aboutUrl(args.get("--about-url")) @@ -176,8 +140,7 @@ public class TestJpackageOperation { .winShortcut(true) .winShortcutPrompt(true) .winUpdateUrl(args.get("--win-update-url")) - .winUpgradeUuid(args.get("--win-upgrade-uuid")) - .filename("filename"); + .winUpgradeUuid(args.get("--win-upgrade-uuid")); assertEquals(options.size(), args.size(), "Wrong number of arguments"); @@ -188,9 +151,59 @@ public class TestJpackageOperation { } + @Test + void testCreatePackage() throws Exception { + var tmpdir = Files.createTempDirectory("bld-jpackage-test").toFile(); + tmpdir.deleteOnExit(); + + var options = new JpackageOptions() + .input("lib/bld") + .name("bld") + .mainJar("bld-wrapper.jar") + .javaOptions("--enable-preview") + .dest(tmpdir.getAbsolutePath()) + .verbose(true); + + var os = System.getProperty("os.version"); + if (os.endsWith("MANJARO")) { + options.type(JpackageOptions.PackageType.DEB); + } + + var jpackage = new JpackageOperation().jpackageOptions(options); + jpackage.execute(); + + var files = tmpdir.listFiles(); + assertNotNull(files, "files should not be null"); + assertTrue(files.length > 0, "No files found"); + + assertTrue(files[0].getName().matches("bld.*\\.[A-Za-z]{3}"), "Package not found"); + + FileUtils.deleteDirectory(tmpdir); + } + + @Test + void testHelp() { + var jpackage = new JpackageOperation().addArgs("--help"); + assertDoesNotThrow(jpackage::execute); + } + + @Test + void testNoArguments() { + var jpackage = new JpackageOperation(); + assertTrue(jpackage.options().isEmpty(), "options not empty"); + assertTrue(jpackage.jpackageOptions().isEmpty(), "jpackage options not empty"); + assertThrows(ExitStatusException.class, jpackage::execute); + } + + @Test + void testOptions() { + var jpackage = new JpackageOperation().options("src/test/resources/options_verbose.txt"); + assertDoesNotThrow(jpackage::execute); + } + @Test void testVersion() { - var jpackage = new JpackageOperation().addArgs("--version"); + var jpackage = new JpackageOperation().addArgs("--verbose", "--version"); assertDoesNotThrow(jpackage::execute); } } diff --git a/src/test/resources/options_verbose.txt b/src/test/resources/options_verbose.txt new file mode 100644 index 0000000..2aa4b63 --- /dev/null +++ b/src/test/resources/options_verbose.txt @@ -0,0 +1 @@ +--verbose --version \ No newline at end of file diff --git a/src/test/resources/options_version.txt b/src/test/resources/options_version.txt new file mode 100644 index 0000000..e0f9217 --- /dev/null +++ b/src/test/resources/options_version.txt @@ -0,0 +1 @@ +--version \ No newline at end of file From e2cc7a6782466f9476deb62ba043e437244fd7a5 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 2 Aug 2024 18:25:39 -0700 Subject: [PATCH 08/27] Improved @filename options parsing --- src/main/java/rife/bld/operations/JlinkOperation.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/rife/bld/operations/JlinkOperation.java b/src/main/java/rife/bld/operations/JlinkOperation.java index 01130e7..1f04801 100644 --- a/src/main/java/rife/bld/operations/JlinkOperation.java +++ b/src/main/java/rife/bld/operations/JlinkOperation.java @@ -107,7 +107,16 @@ public class JlinkOperation extends AbstractToolProviderOperation 1 && !splitArgs[1].isEmpty()) { + list.add(splitArgs[1]); + } + } + } } } } From b94b23af56e119108d1d52836f5058515dd5bcb7 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 2 Aug 2024 18:26:00 -0700 Subject: [PATCH 09/27] Clear command line arguments on execution --- .../AbstractToolProviderOperation.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java index 3513436..b435f54 100644 --- a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java +++ b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java @@ -85,18 +85,24 @@ public abstract class AbstractToolProviderOperation + * Command line arguments are automatically cleared. + * + * @throws Exception if an error occurred + */ @Override public void execute() throws Exception { if (toolArgs_.isEmpty()) { - System.err.println("No " + toolName_ + " arguments specified."); + System.err.println("No " + toolName_ + " command line arguments specified."); throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); } - var tool = ToolProvider.findFirst(toolName_).orElseThrow(() -> - new IllegalStateException("No " + toolName_ + " tool found.")); - var stderr = new StringWriter(); var stdout = new StringWriter(); try (var err = new PrintWriter(stderr); var out = new PrintWriter(stdout)) { + var tool = ToolProvider.findFirst(toolName_).orElseThrow(() -> + new IllegalStateException("No " + toolName_ + " tool found.")); var status = tool.run(out, err, toolArgs_.toArray(new String[0])); out.flush(); err.flush(); @@ -115,6 +121,8 @@ public abstract class AbstractToolProviderOperation Date: Fri, 2 Aug 2024 18:27:03 -0700 Subject: [PATCH 10/27] Added functional tests for jlink and jmod --- classes/META-INF/MANIFEST.MF | 3 + classes/dev/mccue/tree/Tree.class | Bin 0 -> 604 bytes classes/module-info.class | Bin 0 -> 237 bytes .../bld/operations/TestJlinkOperation.java | 28 +++++++- .../bld/operations/TestJmodOperation.java | 61 +++++++++++++++++- .../bld/operations/TestJpackageOperation.java | 10 +-- src/test/resources/jlink/.gitignore | 2 + src/test/resources/jlink/Makefile | 40 ++++++++++++ .../jlink/dev.mccue.apple/dev.mccue.apple.iml | 11 ++++ .../jlink/dev.mccue.apple/legal/LICENSE | 1 + .../res/dev/mccue/apple/color.txt | 1 + .../src/dev/mccue/apple/Apple.java | 20 ++++++ .../dev.mccue.apple/src/module-info.java | 3 + .../jlink/dev.mccue.tree/dev.mccue.tree.iml | 12 ++++ .../src/dev/mccue/tree/Tree.java | 15 +++++ .../jlink/dev.mccue.tree/src/module-info.java | 3 + .../resources/{ => jlink}/options_verbose.txt | 0 .../resources/{ => jlink}/options_version.txt | 0 18 files changed, 200 insertions(+), 10 deletions(-) create mode 100644 classes/META-INF/MANIFEST.MF create mode 100644 classes/dev/mccue/tree/Tree.class create mode 100644 classes/module-info.class create mode 100644 src/test/resources/jlink/.gitignore create mode 100644 src/test/resources/jlink/Makefile create mode 100644 src/test/resources/jlink/dev.mccue.apple/dev.mccue.apple.iml create mode 100644 src/test/resources/jlink/dev.mccue.apple/legal/LICENSE create mode 100644 src/test/resources/jlink/dev.mccue.apple/res/dev/mccue/apple/color.txt create mode 100644 src/test/resources/jlink/dev.mccue.apple/src/dev/mccue/apple/Apple.java create mode 100644 src/test/resources/jlink/dev.mccue.apple/src/module-info.java create mode 100644 src/test/resources/jlink/dev.mccue.tree/dev.mccue.tree.iml create mode 100644 src/test/resources/jlink/dev.mccue.tree/src/dev/mccue/tree/Tree.java create mode 100644 src/test/resources/jlink/dev.mccue.tree/src/module-info.java rename src/test/resources/{ => jlink}/options_verbose.txt (100%) rename src/test/resources/{ => jlink}/options_version.txt (100%) diff --git a/classes/META-INF/MANIFEST.MF b/classes/META-INF/MANIFEST.MF new file mode 100644 index 0000000..4512657 --- /dev/null +++ b/classes/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Created-By: 17.0.12 (Eclipse Adoptium) + diff --git a/classes/dev/mccue/tree/Tree.class b/classes/dev/mccue/tree/Tree.class new file mode 100644 index 0000000000000000000000000000000000000000..77d34f1c431dad0fc0b405e1fcb2182b783158d2 GIT binary patch literal 604 zcmZuuTT22#7(L^v?qNjBmWMnV0?F#*?>Omo)AJC7A zzLCJ9Ue3&%Ip6utH}moN_730-2L=+*IFcq(NHgU6_RzLm+wWP|-M(-lhV-fQWpvJ< z)#@FN3`6Nb3@y)bVqw{Xfh(*Fg$6h@9a)$hb0+4o@XN0K^cV?`T!NTPORZ@m8CW-= z^rLnZ3fpUNEHV^k?!*e~mcT#`nu4N<63PsESJ+`Qj3s%k)atES&5uM46=~VT3RW3X zPT&S1Ly^?8A*r$Sdn8;(g=53SCaM(SpKuI(prX1yrLX<9sCO8Wm%)QzSZGOKT*Y2j zgtvCrB_`?FlIqH}`~M4#b`Xb-Xi6p4)x<|C0*-0q1bq~sfkr@@aEneAS{bdW!!g(k zZ5Xx*)isfX^hktCS|tO;W+vcwW9ZMc|EcECv4h=j^~tmmP<(|kL5>RYBNRqh8ewhL XCyyk#WMROhfLRpiw;A?`OJM&CXwP~$ literal 0 HcmV?d00001 diff --git a/classes/module-info.class b/classes/module-info.class new file mode 100644 index 0000000000000000000000000000000000000000..647decb36d5a02653defcfd61f2eb33ecfae1f8a GIT binary patch literal 237 zcmYk0F%E)25Jmq0ihu%%mR`X{Y^-eUOiVn%x~v8TAt2P8%fbVADB}V#I>pSNH$RjA zdOw~3Ht-2fnnhJ27xC?snIMAy2iS$zoZv>XW~mUBWcNbKDU6;49Sd4E!;oOLc6Q{Y zvWy63xMoWht_a@m0nhV9ogIRG$f`ofZJbELaM#69e|xd#;>ypmYyeF~?Muf*2@N`2 WHRl*~ScBC7HpbodZJrVaREQ7YS}~Xa literal 0 HcmV?d00001 diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index 7845508..c47f02f 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -7,9 +7,12 @@ package rife.bld.operations; import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; +import rife.tools.FileUtils; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.util.HashMap; -import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -68,8 +71,27 @@ public class TestJlinkOperation { .disablePlugin("system-modules") .listPlugins(); assertDoesNotThrow(jlink::execute); + } - assertTrue(jlink.toolArgs().containsAll(List.of("vm", "system-modules"))); + @Test + void testExecute() throws IOException { + var tmpdir = Files.createTempDirectory("bld-jlink-test").toFile(); + tmpdir.deleteOnExit(); + + var output = new File(tmpdir, "jlink"); + output.deleteOnExit(); + + var options = new JlinkOptions() + .modulePath("src/test/resources/jlink/build/jmod") + .addModules("dev.mccue.tree") + .launcher("tree", "dev.mccue.tree", "dev.mccue.tree.Tree") + .output(output.getAbsolutePath()); + var jlink = new JlinkOperation().jlinkOptions(options); + + assertDoesNotThrow(jlink::execute); + assertTrue(output.exists(), "Output dir does not exist"); + + FileUtils.deleteDirectory(tmpdir); } @Test @@ -88,7 +110,7 @@ public class TestJlinkOperation { @Test void testOptions() { - var jlink = new JlinkOperation().options("src/test/resources/options_verbose.txt"); + var jlink = new JlinkOperation().options("src/test/resources/jlink/options_verbose.txt"); assertDoesNotThrow(jlink::execute); } diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index 1dbbfaa..aa4550b 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -7,12 +7,17 @@ package rife.bld.operations; import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; +import rife.tools.FileUtils; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.HashMap; import static org.junit.jupiter.api.Assertions.*; +import static rife.bld.operations.JmodOperation.OperationMode; public class TestJmodOperation { @Test @@ -68,10 +73,60 @@ public class TestJmodOperation { } } + @Test + void testCreate() throws IOException { + var tmpdir = Files.createTempDirectory("bld-jmod-test").toFile(); + tmpdir.deleteOnExit(); + + var mod = new File(tmpdir, "dev.mccue.tree.jmod"); + mod.deleteOnExit(); + + var options = new JmodOptions() + .legalNotices("src/test/resources/jlink/dev.mccue.apple/legal") + .classpath("src/test/resources/jlink/build/jar/dev.mccue.apple.jar"); + var jmod = new JmodOperation() + .operationMode(OperationMode.CREATE) + .jmodFile(mod.getAbsolutePath()) + .jmodOptions(options); + + assertDoesNotThrow(jmod::execute); + assertTrue(mod.exists(), "mod does not exist"); + + FileUtils.deleteDirectory(tmpdir); + } + + @Test + void testExecute() throws IOException { + var tmpdir = Files.createTempDirectory("bld-jmod-test").toFile(); + tmpdir.deleteOnExit(); + + var mod = new File(tmpdir, "dev.mccue.tree.jmod"); + mod.deleteOnExit(); + + var options = new JmodOptions().classpath("src/test/resources/jlink/build/jar/dev.mccue.tree.jar"); + var jmod = new JmodOperation() + .operationMode(OperationMode.CREATE) + .jmodFile(mod.getAbsolutePath()) + .jmodOptions(options); + + assertDoesNotThrow(jmod::execute); + assertTrue(mod.exists(), "mod does not exist"); + + jmod.jmodOptions().clear(); + + jmod.operationMode(OperationMode.DESCRIBE); + assertDoesNotThrow(jmod::execute, "describe mod failed"); + + jmod.operationMode(OperationMode.LIST); + assertDoesNotThrow(jmod::execute, "list mod failed"); + + FileUtils.deleteDirectory(tmpdir); + } + @Test void testHelp() { var jmod = new JmodOperation() - .operationMode(JmodOperation.OperationMode.HASH) + .operationMode(OperationMode.HASH) .jmodFile("foo") .addArgs("--help-extra"); assertDoesNotThrow(jmod::execute); @@ -87,14 +142,14 @@ public class TestJmodOperation { @Test void testOptions() { - var jpackage = new JpackageOperation().options("src/test/resources/options_version.txt"); + var jpackage = new JpackageOperation().options("src/test/resources/jlink/options_version.txt"); assertDoesNotThrow(jpackage::execute); } @Test void testVersion() { var jmod = new JmodOperation() - .operationMode(JmodOperation.OperationMode.DESCRIBE) + .operationMode(OperationMode.DESCRIBE) .jmodFile("foo") .addArgs("--version"); assertDoesNotThrow(jmod::execute); diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index 8a1178b..4c32c01 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -13,6 +13,8 @@ import java.nio.file.Files; import java.util.HashMap; import static org.junit.jupiter.api.Assertions.*; +import static rife.bld.operations.JpackageOptions.Launcher; +import static rife.bld.operations.JpackageOptions.PackageType; public class TestJpackageOperation { @@ -82,7 +84,7 @@ public class TestJpackageOperation { var options = new JpackageOptions() .aboutUrl(args.get("--about-url")) - .addLauncher(new JpackageOptions.Launcher("name", "path")) + .addLauncher(new Launcher("name", "path")) .addModules(args.get("--add-modules").split(",")) .appContent(args.get("--app-content").split(",")) .appImage(args.get("--app-image")) @@ -128,7 +130,7 @@ public class TestJpackageOperation { .runtimeImage(args.get("--runtime-image")) .stripDebug(true) .temp(args.get("--temp")) - .type(JpackageOptions.PackageType.EXE) + .type(PackageType.EXE) .vendor(args.get("--vendor")) .verbose(true) .winConsole(true) @@ -166,7 +168,7 @@ public class TestJpackageOperation { var os = System.getProperty("os.version"); if (os.endsWith("MANJARO")) { - options.type(JpackageOptions.PackageType.DEB); + options.type(PackageType.DEB); } var jpackage = new JpackageOperation().jpackageOptions(options); @@ -197,7 +199,7 @@ public class TestJpackageOperation { @Test void testOptions() { - var jpackage = new JpackageOperation().options("src/test/resources/options_verbose.txt"); + var jpackage = new JpackageOperation().options("src/test/resources/jlink/options_verbose.txt"); assertDoesNotThrow(jpackage::execute); } diff --git a/src/test/resources/jlink/.gitignore b/src/test/resources/jlink/.gitignore new file mode 100644 index 0000000..edea9d9 --- /dev/null +++ b/src/test/resources/jlink/.gitignore @@ -0,0 +1,2 @@ +build/javac +build/jar \ No newline at end of file diff --git a/src/test/resources/jlink/Makefile b/src/test/resources/jlink/Makefile new file mode 100644 index 0000000..c7f0557 --- /dev/null +++ b/src/test/resources/jlink/Makefile @@ -0,0 +1,40 @@ +.PHONY: clean +clean: + rm -rf build + +.PHONY: compile +compile: clean + javac -d build/javac --module-source-path "./*/src" --module dev.mccue.tree,dev.mccue.apple + +.PHONY: package +package: compile + mkdir -p build/jar + + jar --create --file build/jar/dev.mccue.apple.jar \ + -C build/javac/dev.mccue.apple . \ + -C dev.mccue.apple/res . + jar --create --file build/jar/dev.mccue.tree.jar \ + -C build/javac/dev.mccue.tree . + +.PHONY: link +link: package + mkdir -p build/jmod + + jmod create \ + --legal-notices dev.mccue.apple/legal \ + --class-path build/jar/dev.mccue.apple.jar \ + build/jmod/dev.mccue.apple.jmod + + jmod create \ + --class-path build/jar/dev.mccue.tree.jar \ + build/jmod/dev.mccue.tree.jmod + + jlink \ + --module-path build/jmod \ + --add-modules dev.mccue.tree \ + --launcher tree=dev.mccue.tree/dev.mccue.tree.Tree \ + --output build/jlink + +.PHONY: test +test: link + ./build/jlink/bin/tree diff --git a/src/test/resources/jlink/dev.mccue.apple/dev.mccue.apple.iml b/src/test/resources/jlink/dev.mccue.apple/dev.mccue.apple.iml new file mode 100644 index 0000000..c90834f --- /dev/null +++ b/src/test/resources/jlink/dev.mccue.apple/dev.mccue.apple.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/jlink/dev.mccue.apple/legal/LICENSE b/src/test/resources/jlink/dev.mccue.apple/legal/LICENSE new file mode 100644 index 0000000..6a332dd --- /dev/null +++ b/src/test/resources/jlink/dev.mccue.apple/legal/LICENSE @@ -0,0 +1 @@ +Apples are GOD'S creation. You have no right to them. \ No newline at end of file diff --git a/src/test/resources/jlink/dev.mccue.apple/res/dev/mccue/apple/color.txt b/src/test/resources/jlink/dev.mccue.apple/res/dev/mccue/apple/color.txt new file mode 100644 index 0000000..46f29e8 --- /dev/null +++ b/src/test/resources/jlink/dev.mccue.apple/res/dev/mccue/apple/color.txt @@ -0,0 +1 @@ +red \ No newline at end of file diff --git a/src/test/resources/jlink/dev.mccue.apple/src/dev/mccue/apple/Apple.java b/src/test/resources/jlink/dev.mccue.apple/src/dev/mccue/apple/Apple.java new file mode 100644 index 0000000..8afbc8b --- /dev/null +++ b/src/test/resources/jlink/dev.mccue.apple/src/dev/mccue/apple/Apple.java @@ -0,0 +1,20 @@ +package dev.mccue.apple; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Objects; + +public final class Apple { + public String color() { + try { + return new String( + Objects.requireNonNull( + Apple.class.getResourceAsStream("/dev/mccue/apple/color.txt") + ).readAllBytes() + ); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + } +} diff --git a/src/test/resources/jlink/dev.mccue.apple/src/module-info.java b/src/test/resources/jlink/dev.mccue.apple/src/module-info.java new file mode 100644 index 0000000..1e2b64b --- /dev/null +++ b/src/test/resources/jlink/dev.mccue.apple/src/module-info.java @@ -0,0 +1,3 @@ +module dev.mccue.apple { + exports dev.mccue.apple; +} \ No newline at end of file diff --git a/src/test/resources/jlink/dev.mccue.tree/dev.mccue.tree.iml b/src/test/resources/jlink/dev.mccue.tree/dev.mccue.tree.iml new file mode 100644 index 0000000..3dcb8cc --- /dev/null +++ b/src/test/resources/jlink/dev.mccue.tree/dev.mccue.tree.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/jlink/dev.mccue.tree/src/dev/mccue/tree/Tree.java b/src/test/resources/jlink/dev.mccue.tree/src/dev/mccue/tree/Tree.java new file mode 100644 index 0000000..aa8ebe9 --- /dev/null +++ b/src/test/resources/jlink/dev.mccue.tree/src/dev/mccue/tree/Tree.java @@ -0,0 +1,15 @@ +package dev.mccue.tree; + +import dev.mccue.apple.Apple; + +public final class Tree { + public Apple bearFruit() { + return new Apple(); + } + + public static void main(String[] args) { + System.out.println( + new Tree().bearFruit().color() + ); + } +} diff --git a/src/test/resources/jlink/dev.mccue.tree/src/module-info.java b/src/test/resources/jlink/dev.mccue.tree/src/module-info.java new file mode 100644 index 0000000..e481ad5 --- /dev/null +++ b/src/test/resources/jlink/dev.mccue.tree/src/module-info.java @@ -0,0 +1,3 @@ +module dev.mccue.tree { + requires dev.mccue.apple; +} \ No newline at end of file diff --git a/src/test/resources/options_verbose.txt b/src/test/resources/jlink/options_verbose.txt similarity index 100% rename from src/test/resources/options_verbose.txt rename to src/test/resources/jlink/options_verbose.txt diff --git a/src/test/resources/options_version.txt b/src/test/resources/jlink/options_version.txt similarity index 100% rename from src/test/resources/options_version.txt rename to src/test/resources/jlink/options_version.txt From c38594a1732a0115ac650c4e6289ecac51b41b84 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 2 Aug 2024 18:37:28 -0700 Subject: [PATCH 11/27] Foce added jlink build directory --- .../jlink/build/jar/dev.mccue.apple.jar | Bin 0 -> 1693 bytes .../resources/jlink/build/jar/dev.mccue.tree.jar | Bin 0 -> 1440 bytes .../jlink/build/jmod/dev.mccue.apple.jmod | Bin 0 -> 1526 bytes .../jlink/build/jmod/dev.mccue.tree.jmod | Bin 0 -> 1086 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/test/resources/jlink/build/jar/dev.mccue.apple.jar create mode 100644 src/test/resources/jlink/build/jar/dev.mccue.tree.jar create mode 100644 src/test/resources/jlink/build/jmod/dev.mccue.apple.jmod create mode 100644 src/test/resources/jlink/build/jmod/dev.mccue.tree.jmod diff --git a/src/test/resources/jlink/build/jar/dev.mccue.apple.jar b/src/test/resources/jlink/build/jar/dev.mccue.apple.jar new file mode 100644 index 0000000000000000000000000000000000000000..cc64501bfd4e4000bcd9f4455ed22e8f70f1b5b7 GIT binary patch literal 1693 zcmWIWW@Zs#;Nak3_};}7$$$hn8CV#6T|*poJ^kGD|D9rBU}gyLX6FE@V1go=4H7)9#7I)A!XHCvqA0L~8yL#AI6@^yVPH$!Z z5O6HD^WuD;e`ik5|8xEKN0tq44j(q#tP7f_em(hJ6USqFg>##xwFI8odSc3|h!cxE zDw%e-E^J)b7;Mo}_gR5&)0LTW2YbVk6c?!;y#4&D??*MynGbS&Srs#;&kYf;eDsO0 zu*8*$Hl+^40rShVgbsg zq?YM}LIAr8peR^HZgO&IDjszLDC!am3UVN-u_p{^EUFzrdLSX38}#1)a)Lk|-?qI0 zR^ONd92^{vh?QJDA3V7?Bgx49&=iLsS4!7!zOZ#`wfBepm-NqgEUNp~Zxpv%Q2mnH z_iuZv-&L+F|Ni>>_V*0)9(T5J`f#O`q)b#6@qc4{`%}*T?6+I}mn`PknZEA*D)AQ2 z!!`mlez9K(n)te$)#Q+q`@Bfo@jY?X+KzQ2P*M{mJnpP}2H?=KNgr&>M zOGB8eer37s?)&OzN|)Z6{#T(-Ci3;>d0VPkE@#B(FUsPJ%}dz(?QjI|!cgAN5du4w zJ~k8MTq+{0eO>ymg7+D>PswlGHc9?Cd*d@l^y4?qH$;E$@J^WddbeZ9VWF^+HA%e- zHZKnTyyus?YNU4ZjN_%eOy4K%WDo_D+A^$1_#>2NOSsc6ej?zR!+U z%QqRfUD(js&N@BZI=5rel82hhDyL6MXPS~D96dRIb&b&cn{OFkaMufLyZJ0= zdBW~ycjXt=DM4Mm-W`iSl~g`s`ni6_@6M&%cO)OYdwxvStiO!y#;=KKpItT{l;pfG zRm><=@zCIKK4)cLc8|sfldcMzD>fo?99Jw!jj9Ld!kab$XP+_xlO{8AE)?rPEk-1< zq?Y9Toctoal8O>-FJDNG?vGFW#R^mjGzw@oBa;XNYTAR9IG{oa6~IdwP!WZ$6}g}Q z6-fwS3uMBzA{9{RCLm`;P=SH~2Z2nC;svCgivfFXM0NQ>V8}soFK!*6{EGmGp*mo> z8Mi)Aenx=TDEeTz8#RoP;}Vp=5kL|c^dNUaY=!7X%I(PE1&Vs)hy+DF0=NVHk8Th= VAq04{vVoLx0O1#)dnbbf3jnHm2`2ym literal 0 HcmV?d00001 diff --git a/src/test/resources/jlink/build/jar/dev.mccue.tree.jar b/src/test/resources/jlink/build/jar/dev.mccue.tree.jar new file mode 100644 index 0000000000000000000000000000000000000000..93abdd333c90e8982f5d7c5d604168157946c7aa GIT binary patch literal 1440 zcmWIWW@Zs#;Nak3_};}7$$$hn8CV#6T|*poJ^kGD|D9rBU}gyLX6FE@V1gcKl@;Zxsl zzgbxLP(AW4Bk%qThHlocKZMLpyb#E{Eyz-0q5M8C=2xBkpum>oIMBQb=#95fk8&|E z03!fBrdWWoDXC@pprF960w@Yrk(-=cnu{g@o^c~ z*NZxSlO`9RxAnYdA9tTYCgHRb7n}PnH@3*OKXWSt`qZ1EpRcJ^zdJ*5_j)E#c_WFf zzf_M)IKOnWv)K1q?ULZ!KJ~fEy>7-M8d}v`jEh>q6^|mv$;_n9#m(VaDPXqvo5_l&m_1T;rxj?X@%tbatP$HSnN} z^D*AN21y!|ez~ujaqIr10>;ojS84BvWgNI6LBh*n3_n#-rj9wNF+i?CN$B zH;z5S|Jz5|cSbYoY^G-c3+|`gP|#~V>kmpbE9Dw|Di|3UVu1NHz?+dtgaI`IVc8dy z!%+b|%YyPdx>n>|2g=_FU<+izwIbzqbQ6%1Gbnc=z(F7rBd>zAb1`5~(Wow81@tW> z2jJEL$^!^+2C4&=BXH{j8OW@Zs#;Nak3_};}7$$$hTf$Zd*#Ny)AV*T9wl+v73-ORkSd_Az3Z?7R= zlY@Zke~zZ6MV-^)4!Y*7$$9JJV{>p<4;!nZ&t?VBHj-_^9obU7R%<1`muK)hX zvcb*a!)BXxLG#qFC%x&fKJk@&n93@DHaBrWZQHtqyPTHW zyw$6ddbLsd8)JYsJI4=ikE08LzPJU%xcw=E*`(P_14uocjo-&AcHH$51tn3dHL#i`d%zu#lkh?wd4y)Db0)>YR^-|M3!q= zEPEn8C1u*PtWQNBi$Gz_&e3gKpWpMLA6H7(Z@#c~Yqj@>{g?F5 zcr2>>)^8NITTuOy+V^jJtKU_wEC2rb`}X$?^B#A$ar$tjl%z~l7V&>$eEU<*{_M9~ z{g*7}*qOfW{VMSm&%-tXGk&pO37Yu2oYmxzll#0#+vA-}Q`;A+uZ>DtzCd`|+Si8a zADUJyIybc~QiP?;%1c9-tA1sPXG)jen*LXzPbTv9=6PGHSuSV9=r79Ri_J^e z`|WT9@4`^t&k+JUmOeHU<6J5ttbJYjuY&g(w@=A$+%`%6ID6wWNA%-2&NoDV@9<8T z`Fgiw$YG(dk~K-a3pOtf{=Daxx@x3$@{Hr9yiDIG^{p4)bga-{-@PTMs1vU!Hr#vCs*(SWph%~6La)^Je^(r zf?bPsG){QxhI#0Cg%*4-59AN?0A+xaXU<;^?l_|#dcs4;JM_fqaE((w=QRQ~PKIlo z^f-H!8SD!o$&5C0pn0ZX8yT5I7!V~6avlYhIH&+;`4ixcY7BDr0%d3fcmZU>jKP+@ z(M>`Qa!__efD&Ltz)ZrEInfP74sTFQA;2nN6yP!t9&hNzAqOTXk`Uk@&^VMR3-D%T Q14*+2VGhvo1uP&Q0A@iK%>V!Z literal 0 HcmV?d00001 diff --git a/src/test/resources/jlink/build/jmod/dev.mccue.tree.jmod b/src/test/resources/jlink/build/jmod/dev.mccue.tree.jmod new file mode 100644 index 0000000000000000000000000000000000000000..cceacbdc788eaf5d8a32fd277b4536183e07b0c7 GIT binary patch literal 1086 zcmebBWn>8OW@Zs#;Nak3_};}7$$$hTf$Zd*#Ny)AV*T9wl+v73-ORkSd_Az3Z=WMy zlLL=yJ)@&Tqs#QTgN}E06umxox#X+Gz{(M^dn1-7Pa4?4x!qt9(Ewk?Nia>DkavIkQq z@oig|C3kx5rN8V-R-G9N*&HD9+ zkhzH$0(rLuSxPLF-{-~rs*^v!o1H_F<3RH&pm*K^F>VjbAbHr=HN;WZ)6Y%c*U`_@ z%{4eg&)4m<@0rs+-nx1hdA)VD&Yd~GImqCO@q?#DdS1Rdp1v1LSFv!-crE!tQc5#p zhuZTLF_Gn37R#Q9Pf3~fEbCLz$0AT*vvYLY)+aatZF0ox7DXhtq@HRIO(Nd=6deXi2p5z9D~4;g;wyI0A$bp7A$ zE8>lo^dFW!X>c>7(Z=`BwjMo~+sbNhxm`=2-un8&X|<@@L~Z{mVzYl8vyN(y-BrX@ zC6Vx}og+LWeCf=Kb8fzCw7uMvIMv{{tI#FoTJPy69X2P|epoGcX1RS9pKx}>|FHMG zQjAB%BWj Date: Fri, 2 Aug 2024 21:09:45 -0700 Subject: [PATCH 12/27] Use System.out and System.out instead of StringWriter --- .../AbstractToolProviderOperation.java | 59 +++++-------------- .../rife/bld/operations/JlinkOperation.java | 2 +- 2 files changed, 16 insertions(+), 45 deletions(-) diff --git a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java index b435f54..a1f1863 100644 --- a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java +++ b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java @@ -6,8 +6,6 @@ package rife.bld.operations; import rife.bld.operations.exceptions.ExitStatusException; -import java.io.PrintWriter; -import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -33,22 +31,6 @@ public abstract class AbstractToolProviderOperation args) { - args.forEach(this::addArg); + args.forEach((k, v) -> { + toolArgs_.add(k); + if (v != null && !v.isEmpty()) { + toolArgs_.add(v); + } + }); return (T) this; } @@ -88,7 +75,7 @@ public abstract class AbstractToolProviderOperation - * Command line arguments are automatically cleared. + * On success, command line arguments are automatically cleared. * * @throws Exception if an error occurred */ @@ -98,32 +85,16 @@ public abstract class AbstractToolProviderOperation - new IllegalStateException("No " + toolName_ + " tool found.")); - var status = tool.run(out, err, toolArgs_.toArray(new String[0])); - out.flush(); - err.flush(); + var tool = ToolProvider.findFirst(toolName_).orElseThrow(() -> + new IllegalStateException("No " + toolName_ + " tool found.")); - if (status != 0) { - System.out.println(tool.name() + ' ' + String.join(" ", toolArgs_)); - } - - var output = stdout.toString(); - if (!output.isBlank()) { - System.out.println(output); - } - var error = stderr.toString(); - if (!error.isBlank()) { - System.err.println(error); - } - - ExitStatusException.throwOnFailure(status); - } finally { - toolArgs_.clear(); + var status = tool.run(System.out, System.err, toolArgs_.toArray(new String[0])); + if (status != 0) { + System.out.println(tool.name() + ' ' + String.join(" ", toolArgs_)); } + ExitStatusException.throwOnFailure(status); + + toolArgs_.clear(); } /** diff --git a/src/main/java/rife/bld/operations/JlinkOperation.java b/src/main/java/rife/bld/operations/JlinkOperation.java index 1f04801..a266117 100644 --- a/src/main/java/rife/bld/operations/JlinkOperation.java +++ b/src/main/java/rife/bld/operations/JlinkOperation.java @@ -40,7 +40,7 @@ public class JlinkOperation extends AbstractToolProviderOperation addArg("--disable-plugin", plugin)); + disabledPlugins_.forEach(plugin -> addArgs("--disable-plugin", plugin)); addArgs(jlinkOptions_); addArgs(parseOptions()); super.execute(); From 94225dfb7a8f16dc95a388cabed06ec71f4e4b4e Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 2 Aug 2024 21:33:33 -0700 Subject: [PATCH 13/27] Improved @filename support --- src/main/java/rife/bld/operations/JlinkOperation.java | 6 +++--- .../java/rife/bld/operations/TestJlinkOperation.java | 9 ++++++++- src/test/java/rife/bld/operations/TestJmodOperation.java | 3 ++- .../java/rife/bld/operations/TestJpackageOperation.java | 3 ++- src/test/resources/jlink/options_jlink.txt | 2 ++ src/test/resources/jlink/options_verbose.txt | 2 +- 6 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 src/test/resources/jlink/options_jlink.txt diff --git a/src/main/java/rife/bld/operations/JlinkOperation.java b/src/main/java/rife/bld/operations/JlinkOperation.java index a266117..907a817 100644 --- a/src/main/java/rife/bld/operations/JlinkOperation.java +++ b/src/main/java/rife/bld/operations/JlinkOperation.java @@ -100,7 +100,7 @@ public class JlinkOperation extends AbstractToolProviderOperation parseOptions() throws FileNotFoundException { var list = new ArrayList(); @@ -109,10 +109,10 @@ public class JlinkOperation extends AbstractToolProviderOperation 1 && !splitArgs[1].isEmpty()) { + if (splitArgs.length > 1 && !splitArgs[1].isBlank()) { list.add(splitArgs[1]); } } diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index c47f02f..2b04b72 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -110,7 +110,14 @@ public class TestJlinkOperation { @Test void testOptions() { - var jlink = new JlinkOperation().options("src/test/resources/jlink/options_verbose.txt"); + var jlink = new JlinkOperation().options("src/test/resources/jlink/options_verbose.txt", + "src/test/resources/jlink/options_version.txt"); + assertDoesNotThrow(jlink::execute); + } + + @Test + void testParseOptions() { + var jlink = new JlinkOperation().options("src/test/resources/jlink/options_jlink.txt"); assertDoesNotThrow(jlink::execute); } diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index aa4550b..8a63920 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -142,7 +142,8 @@ public class TestJmodOperation { @Test void testOptions() { - var jpackage = new JpackageOperation().options("src/test/resources/jlink/options_version.txt"); + var jpackage = new JpackageOperation().options("src/test/resources/jlink/options_verbose.txt", + "src/test/resources/jlink/options_version.txt"); assertDoesNotThrow(jpackage::execute); } diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index 4c32c01..9bccef0 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -199,7 +199,8 @@ public class TestJpackageOperation { @Test void testOptions() { - var jpackage = new JpackageOperation().options("src/test/resources/jlink/options_verbose.txt"); + var jpackage = new JpackageOperation().options("src/test/resources/jlink/options_verbose.txt", + "src/test/resources/jlink/options_version.txt"); assertDoesNotThrow(jpackage::execute); } diff --git a/src/test/resources/jlink/options_jlink.txt b/src/test/resources/jlink/options_jlink.txt new file mode 100644 index 0000000..f991ca7 --- /dev/null +++ b/src/test/resources/jlink/options_jlink.txt @@ -0,0 +1,2 @@ + --verbose --version + --list-plugins diff --git a/src/test/resources/jlink/options_verbose.txt b/src/test/resources/jlink/options_verbose.txt index 2aa4b63..4342561 100644 --- a/src/test/resources/jlink/options_verbose.txt +++ b/src/test/resources/jlink/options_verbose.txt @@ -1 +1 @@ ---verbose --version \ No newline at end of file +--verbose \ No newline at end of file From f6aa5258efcb4b1c9ff655b14773709d1235adab Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 3 Aug 2024 07:36:35 -0700 Subject: [PATCH 14/27] Normalized tool arguments setup and processing --- .../AbstractToolProviderOperation.java | 122 ++++++++++++------ .../rife/bld/operations/JlinkOperation.java | 61 +++------ .../rife/bld/operations/JmodOperation.java | 63 +++++---- .../bld/operations/JpackageOperation.java | 17 +-- 4 files changed, 137 insertions(+), 126 deletions(-) diff --git a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java index a1f1863..c2ec9bc 100644 --- a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java +++ b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java @@ -6,9 +6,12 @@ package rife.bld.operations; import rife.bld.operations.exceptions.ExitStatusException; +import java.io.File; +import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Scanner; import java.util.spi.ToolProvider; /** @@ -31,47 +34,6 @@ public abstract class AbstractToolProviderOperation args) { - args.forEach((k, v) -> { - toolArgs_.add(k); - if (v != null && !v.isEmpty()) { - toolArgs_.add(v); - } - }); - return (T) this; - } - - /** - * Adds tool command line arguments. - * - * @param args the argument to add - * @return this operation - */ - @SuppressWarnings({"unchecked", "UnusedReturnValue"}) - public T addArgs(List args) { - toolArgs_.addAll(args); - return (T) this; - } - - /** - * Adds tool command line arguments. - * - * @param arg one or more argument - * @return this operation - */ - @SuppressWarnings("unchecked") - public T addArgs(String... arg) { - addArgs(List.of(arg)); - return (T) this; - } - /** * Runs an instance of the tool. *

@@ -85,6 +47,7 @@ public abstract class AbstractToolProviderOperation new IllegalStateException("No " + toolName_ + " tool found.")); @@ -92,17 +55,92 @@ public abstract class AbstractToolProviderOperation args) { + args.forEach((k, v) -> { + toolArgs_.add(k); + if (v != null && !v.isEmpty()) { + toolArgs_.add(v); + } + }); + return (T) this; + } + + /** + * Adds arguments to pass to the tool. + * + * @param args the argument to add + * @return this operation + */ + @SuppressWarnings({"unchecked", "UnusedReturnValue"}) + public T toolArgs(List args) { + toolArgs_.addAll(args); + return (T) this; + } + + /** + * Returns the tool's arguments. * * @return the arguments */ public List toolArgs() { return toolArgs_; } + + /** + * Parses arguments to pass to the tool from the given files. + * + * @param files the list of files + * @return this operation instance + * @throws FileNotFoundException if a file cannot be found + */ + @SuppressWarnings({"unchecked", "UnusedReturnValue"}) + public T toolArgsFromFile(List files) throws FileNotFoundException { + var list = new ArrayList(); + + for (var option : files) { + try (var scanner = new Scanner(new File(option))) { + while (scanner.hasNext()) { + var splitLine = scanner.nextLine().split("--"); + for (String args : splitLine) { + if (!args.isBlank()) { + var splitArgs = args.split(" ", 2); + list.add("--" + splitArgs[0]); + if (splitArgs.length > 1 && !splitArgs[1].isBlank()) { + list.add(splitArgs[1]); + } + } + } + } + } + } + + toolArgs(list); + + return (T) this; + } } diff --git a/src/main/java/rife/bld/operations/JlinkOperation.java b/src/main/java/rife/bld/operations/JlinkOperation.java index 907a817..0956063 100644 --- a/src/main/java/rife/bld/operations/JlinkOperation.java +++ b/src/main/java/rife/bld/operations/JlinkOperation.java @@ -5,12 +5,9 @@ package rife.bld.operations; -import java.io.File; -import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Scanner; /** * Create run-time images using the jlink tool. @@ -21,7 +18,7 @@ import java.util.Scanner; public class JlinkOperation extends AbstractToolProviderOperation { private final List disabledPlugins_ = new ArrayList<>(); private final JlinkOptions jlinkOptions_ = new JlinkOptions(); - private final List options_ = new ArrayList<>(); + private final List fileOptions_ = new ArrayList<>(); public JlinkOperation() { super("jlink"); @@ -40,9 +37,9 @@ public class JlinkOperation extends AbstractToolProviderOperation addArgs("--disable-plugin", plugin)); - addArgs(jlinkOptions_); - addArgs(parseOptions()); + toolArgsFromFile(fileOptions_); + disabledPlugins_.forEach(plugin -> toolArgs("--disable-plugin", plugin)); + toolArgs(jlinkOptions_); super.execute(); } @@ -70,24 +67,14 @@ public class JlinkOperation extends AbstractToolProviderOperation options() { - return options_; + public List fileOptions() { + return fileOptions_; } - // Shouldn't be needed, but jlink doesn't support @filename when called via ToolProvider - private List parseOptions() throws FileNotFoundException { - var list = new ArrayList(); - - for (var option : options_) { - try (var scanner = new Scanner(new File(option))) { - while (scanner.hasNext()) { - var splitLine = scanner.nextLine().split("--"); - for (String args : splitLine) { - if (!args.isBlank()) { - var splitArgs = args.split(" ", 2); - list.add("--" + splitArgs[0]); - if (splitArgs.length > 1 && !splitArgs[1].isBlank()) { - list.add(splitArgs[1]); - } - } - } - } - } - } - - return list; + /** + * List available plugins. + * + * @return this operation instance + */ + public JlinkOperation listPlugins() { + toolArgs("--list-plugins"); + return this; } } diff --git a/src/main/java/rife/bld/operations/JmodOperation.java b/src/main/java/rife/bld/operations/JmodOperation.java index 58ed970..1821598 100644 --- a/src/main/java/rife/bld/operations/JmodOperation.java +++ b/src/main/java/rife/bld/operations/JmodOperation.java @@ -5,8 +5,6 @@ package rife.bld.operations; -import rife.bld.operations.exceptions.ExitStatusException; - import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -18,8 +16,8 @@ import java.util.Map; * @since 2.0.2 */ public class JmodOperation extends AbstractToolProviderOperation { + private final List fileOptions_ = new ArrayList<>(); private final JmodOptions jmodOptions_ = new JmodOptions(); - private final List options_ = new ArrayList<>(); private String jmodFile_; private OperationMode operationMode_; @@ -29,19 +27,40 @@ public class JmodOperation extends AbstractToolProviderOperation @Override public void execute() throws Exception { - if (operationMode_ == null) { - System.err.println("Operation mode not set."); - throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); - } else if (jmodFile_ == null) { - System.err.println("Jmod file not set."); - throw new ExitStatusException(ExitStatusException.EXIT_FAILURE); + if (operationMode_ != null) { + toolArgs(operationMode_.mode); } - addArgs(operationMode_.mode); - addArgs(jmodOptions_); - addArgs(jmodFile_); + + toolArgsFromFile(fileOptions_); + toolArgs(jmodOptions_); + + if (jmodFile_ != null) { + toolArgs(jmodFile_); + } + super.execute(); } + /** + * Retrieves the list of files containing options or mode. + * + * @return the list of files + */ + public List fileOptions() { + return fileOptions_; + } + + /** + * Read options and/or mode from a file. + * + * @param file one or more file + * @return this operation instance + */ + public JmodOperation fileOptions(String... file) { + fileOptions_.addAll(List.of(file)); + return this; + } + /** * Retrieves the name of the JMOD file to create or from which to retrieve information. * @@ -101,26 +120,6 @@ public class JmodOperation extends AbstractToolProviderOperation return this; } - /** - * Retrieves the list of files containing options or mode. - * - * @return the list of files - */ - public List options() { - return options_; - } - - /** - * Read options and/or mode from a file. - * - * @param filename one or more file - * @return this operation instance - */ - public JmodOperation options(String... filename) { - options_.addAll(List.of(filename)); - return this; - } - /** * The operation modes. */ diff --git a/src/main/java/rife/bld/operations/JpackageOperation.java b/src/main/java/rife/bld/operations/JpackageOperation.java index fabada1..ca47e49 100644 --- a/src/main/java/rife/bld/operations/JpackageOperation.java +++ b/src/main/java/rife/bld/operations/JpackageOperation.java @@ -16,8 +16,8 @@ import java.util.Map; * @since 2.0.2 */ public class JpackageOperation extends AbstractToolProviderOperation { + private final List fileOptions_ = new ArrayList<>(); private final JpackageOptions jpackageOptions_ = new JpackageOptions(); - private final List options_ = new ArrayList<>(); public JpackageOperation() { super("jpackage"); @@ -25,8 +25,8 @@ public class JpackageOperation extends AbstractToolProviderOperation '@' + opt).toList()); + toolArgs(fileOptions_.stream().map(opt -> '@' + opt).toList()); + toolArgs(jpackageOptions_); super.execute(); } @@ -35,17 +35,18 @@ public class JpackageOperation extends AbstractToolProviderOperation options(){ - return options_; + public List fileOptions() { + return fileOptions_; } + /** * Read options and/or mode from a file. * - * @param filename one or more file + * @param file one or more file * @return this operation instance */ - public JpackageOperation options(String... filename) { - options_.addAll(List.of(filename)); + public JpackageOperation fileOptions(String... file) { + fileOptions_.addAll(List.of(file)); return this; } From 7a946b17d8d0d3b3a3a0ae410e81aec9418d357e Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 3 Aug 2024 07:37:11 -0700 Subject: [PATCH 15/27] Capture and check stdout in tests --- .../bld/operations/TestJlinkOperation.java | 69 ++++++++---- .../bld/operations/TestJmodOperation.java | 101 ++++++++++-------- .../bld/operations/TestJpackageOperation.java | 79 ++++++++------ 3 files changed, 149 insertions(+), 100 deletions(-) diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index 2b04b72..3d385e1 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -5,18 +5,29 @@ package rife.bld.operations; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; import rife.tools.FileUtils; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.PrintStream; import java.nio.file.Files; import java.util.HashMap; import static org.junit.jupiter.api.Assertions.*; public class TestJlinkOperation { + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + private final PrintStream stdout = System.out; + + @AfterEach + public void tearDown() { + System.setOut(stdout); + } + @Test void testArguments() { var args = new HashMap(); @@ -66,64 +77,76 @@ public class TestJlinkOperation { @Test void testDisablePlugin() { + System.setOut(new PrintStream(outputStreamCaptor)); var jlink = new JlinkOperation() .disablePlugin("vm") .disablePlugin("system-modules") .listPlugins(); assertDoesNotThrow(jlink::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.contains("List of available plugins:"), out); } @Test void testExecute() throws IOException { var tmpdir = Files.createTempDirectory("bld-jlink-test").toFile(); - tmpdir.deleteOnExit(); + try { + var output = new File(tmpdir, "jlink"); - var output = new File(tmpdir, "jlink"); - output.deleteOnExit(); + var options = new JlinkOptions() + .modulePath("src/test/resources/jlink/build/jmod") + .addModules("dev.mccue.tree") + .launcher("tree", "dev.mccue.tree", "dev.mccue.tree.Tree") + .output(output.getAbsolutePath()); + var jlink = new JlinkOperation().jlinkOptions(options); - var options = new JlinkOptions() - .modulePath("src/test/resources/jlink/build/jmod") - .addModules("dev.mccue.tree") - .launcher("tree", "dev.mccue.tree", "dev.mccue.tree.Tree") - .output(output.getAbsolutePath()); - var jlink = new JlinkOperation().jlinkOptions(options); + assertDoesNotThrow(jlink::execute); + assertTrue(output.exists(), "Output dir does not exist"); + } finally { + FileUtils.deleteDirectory(tmpdir); + } + } + @Test + void testFileOptions() { + System.setOut(new PrintStream(outputStreamCaptor)); + var jlink = new JlinkOperation().fileOptions("src/test/resources/jlink/options_verbose.txt", + "src/test/resources/jlink/options_version.txt"); assertDoesNotThrow(jlink::execute); - assertTrue(output.exists(), "Output dir does not exist"); - - FileUtils.deleteDirectory(tmpdir); + var out = outputStreamCaptor.toString(); + assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); } @Test void testHelp() { - var jlink = new JlinkOperation().addArgs("--help"); + var jlink = new JlinkOperation().toolArgs("--help"); assertDoesNotThrow(jlink::execute); + assertTrue(jlink.toolArgs().isEmpty(), "args not empty"); } @Test void testNoArguments() { var jlink = new JlinkOperation(); assertTrue(jlink.jlinkOptions().isEmpty(), "jlink options not empty"); - assertTrue(jlink.options().isEmpty(), "options not empty"); + assertTrue(jlink.fileOptions().isEmpty(), "file options not empty"); assertThrows(ExitStatusException.class, jlink::execute); } - @Test - void testOptions() { - var jlink = new JlinkOperation().options("src/test/resources/jlink/options_verbose.txt", - "src/test/resources/jlink/options_version.txt"); - assertDoesNotThrow(jlink::execute); - } - @Test void testParseOptions() { - var jlink = new JlinkOperation().options("src/test/resources/jlink/options_jlink.txt"); + System.setOut(new PrintStream(outputStreamCaptor)); + var jlink = new JlinkOperation().fileOptions("src/test/resources/jlink/options_jlink.txt"); assertDoesNotThrow(jlink::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.contains("List of available plugins:"), out); } @Test void testVersion() { - var jlink = new JlinkOperation().addArgs("--verbose", "--version"); + System.setOut(new PrintStream(outputStreamCaptor)); + var jlink = new JlinkOperation().toolArgs("--verbose", "--version"); assertDoesNotThrow(jlink::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); } } diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index 8a63920..8b4f520 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -5,12 +5,15 @@ package rife.bld.operations; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; import rife.tools.FileUtils; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.PrintStream; import java.nio.file.Files; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -20,6 +23,14 @@ import static org.junit.jupiter.api.Assertions.*; import static rife.bld.operations.JmodOperation.OperationMode; public class TestJmodOperation { + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + private final PrintStream stdout = System.out; + + @AfterEach + public void tearDown() { + System.setOut(stdout); + } + @Test void testArguments() { var args = new HashMap(); @@ -76,83 +87,81 @@ public class TestJmodOperation { @Test void testCreate() throws IOException { var tmpdir = Files.createTempDirectory("bld-jmod-test").toFile(); - tmpdir.deleteOnExit(); + try { + var mod = new File(tmpdir, "dev.mccue.tree.jmod"); - var mod = new File(tmpdir, "dev.mccue.tree.jmod"); - mod.deleteOnExit(); + var options = new JmodOptions() + .legalNotices("src/test/resources/jlink/dev.mccue.apple/legal") + .classpath("src/test/resources/jlink/build/jar/dev.mccue.apple.jar"); + var jmod = new JmodOperation() + .operationMode(OperationMode.CREATE) + .jmodFile(mod.getAbsolutePath()) + .jmodOptions(options); - var options = new JmodOptions() - .legalNotices("src/test/resources/jlink/dev.mccue.apple/legal") - .classpath("src/test/resources/jlink/build/jar/dev.mccue.apple.jar"); - var jmod = new JmodOperation() - .operationMode(OperationMode.CREATE) - .jmodFile(mod.getAbsolutePath()) - .jmodOptions(options); - - assertDoesNotThrow(jmod::execute); - assertTrue(mod.exists(), "mod does not exist"); - - FileUtils.deleteDirectory(tmpdir); + assertDoesNotThrow(jmod::execute); + assertTrue(mod.exists(), "mod does not exist"); + } finally { + FileUtils.deleteDirectory(tmpdir); + } } @Test void testExecute() throws IOException { var tmpdir = Files.createTempDirectory("bld-jmod-test").toFile(); - tmpdir.deleteOnExit(); + try { + var mod = new File(tmpdir, "dev.mccue.tree.jmod"); - var mod = new File(tmpdir, "dev.mccue.tree.jmod"); - mod.deleteOnExit(); + var options = new JmodOptions().classpath("src/test/resources/jlink/build/jar/dev.mccue.tree.jar"); + var jmod = new JmodOperation() + .operationMode(OperationMode.CREATE) + .jmodFile(mod.getAbsolutePath()) + .jmodOptions(options); - var options = new JmodOptions().classpath("src/test/resources/jlink/build/jar/dev.mccue.tree.jar"); - var jmod = new JmodOperation() - .operationMode(OperationMode.CREATE) - .jmodFile(mod.getAbsolutePath()) - .jmodOptions(options); + assertDoesNotThrow(jmod::execute); + assertTrue(mod.exists(), "mod does not exist"); - assertDoesNotThrow(jmod::execute); - assertTrue(mod.exists(), "mod does not exist"); + jmod.jmodOptions().clear(); - jmod.jmodOptions().clear(); + jmod.operationMode(OperationMode.DESCRIBE); + assertDoesNotThrow(jmod::execute, "describe mod failed"); - jmod.operationMode(OperationMode.DESCRIBE); - assertDoesNotThrow(jmod::execute, "describe mod failed"); - - jmod.operationMode(OperationMode.LIST); - assertDoesNotThrow(jmod::execute, "list mod failed"); - - FileUtils.deleteDirectory(tmpdir); + jmod.operationMode(OperationMode.LIST); + assertDoesNotThrow(jmod::execute, "list mod failed"); + } finally { + FileUtils.deleteDirectory(tmpdir); + } } @Test void testHelp() { - var jmod = new JmodOperation() - .operationMode(OperationMode.HASH) - .jmodFile("foo") - .addArgs("--help-extra"); + var jmod = new JmodOperation().toolArgs("--help-extra"); assertDoesNotThrow(jmod::execute); + assertTrue(jmod.toolArgs().isEmpty(), "args not empty"); } @Test void testNoArguments() { var jmod = new JmodOperation(); - assertTrue(jmod.options().isEmpty(), "options not empty"); + assertTrue(jmod.fileOptions().isEmpty(), "file options not empty"); assertTrue(jmod.jmodOptions().isEmpty(), "jmod options not empty"); assertThrows(ExitStatusException.class, jmod::execute); } @Test - void testOptions() { - var jpackage = new JpackageOperation().options("src/test/resources/jlink/options_verbose.txt", - "src/test/resources/jlink/options_version.txt"); - assertDoesNotThrow(jpackage::execute); + void testFileOptions() { + System.setOut(new PrintStream(outputStreamCaptor)); + var jmod = new JmodOperation().fileOptions("src/test/resources/jlink/options_version.txt"); + assertDoesNotThrow(jmod::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); } @Test void testVersion() { - var jmod = new JmodOperation() - .operationMode(OperationMode.DESCRIBE) - .jmodFile("foo") - .addArgs("--version"); + System.setOut(new PrintStream(outputStreamCaptor)); + var jmod = new JmodOperation().toolArgs("--version"); assertDoesNotThrow(jmod::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); } } diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index 9bccef0..940bef5 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -5,10 +5,13 @@ package rife.bld.operations; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import rife.bld.operations.exceptions.ExitStatusException; import rife.tools.FileUtils; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.nio.file.Files; import java.util.HashMap; @@ -17,6 +20,13 @@ import static rife.bld.operations.JpackageOptions.Launcher; import static rife.bld.operations.JpackageOptions.PackageType; public class TestJpackageOperation { + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + private final PrintStream stdout = System.out; + + @AfterEach + public void tearDown() { + System.setOut(stdout); + } @Test void testArguments() { @@ -156,57 +166,64 @@ public class TestJpackageOperation { @Test void testCreatePackage() throws Exception { var tmpdir = Files.createTempDirectory("bld-jpackage-test").toFile(); - tmpdir.deleteOnExit(); + try { + var options = new JpackageOptions() + .input("lib/bld") + .name("bld") + .mainJar("bld-wrapper.jar") + .javaOptions("--enable-preview") + .dest(tmpdir.getAbsolutePath()) + .verbose(true); - var options = new JpackageOptions() - .input("lib/bld") - .name("bld") - .mainJar("bld-wrapper.jar") - .javaOptions("--enable-preview") - .dest(tmpdir.getAbsolutePath()) - .verbose(true); + var os = System.getProperty("os.version"); + if (os.endsWith("MANJARO")) { + options.type(PackageType.DEB); + } - var os = System.getProperty("os.version"); - if (os.endsWith("MANJARO")) { - options.type(PackageType.DEB); + var jpackage = new JpackageOperation().jpackageOptions(options); + jpackage.execute(); + + var files = tmpdir.listFiles(); + assertNotNull(files, "files should not be null"); + assertTrue(files.length > 0, "no files found"); + + assertTrue(files[0].getName().matches("bld.*\\.[A-Za-z]{3}"), "Package not found"); + } finally { + FileUtils.deleteDirectory(tmpdir); } + } - var jpackage = new JpackageOperation().jpackageOptions(options); - jpackage.execute(); - - var files = tmpdir.listFiles(); - assertNotNull(files, "files should not be null"); - assertTrue(files.length > 0, "No files found"); - - assertTrue(files[0].getName().matches("bld.*\\.[A-Za-z]{3}"), "Package not found"); - - FileUtils.deleteDirectory(tmpdir); + @Test + void testFileOptions() { + System.setOut(new PrintStream(outputStreamCaptor)); + var jpackage = new JpackageOperation().fileOptions("src/test/resources/jlink/options_verbose.txt", + "src/test/resources/jlink/options_version.txt"); + assertDoesNotThrow(jpackage::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); } @Test void testHelp() { - var jpackage = new JpackageOperation().addArgs("--help"); + var jpackage = new JpackageOperation().toolArgs("--help"); assertDoesNotThrow(jpackage::execute); + assertTrue(jpackage.toolArgs().isEmpty(), "args not empty"); } @Test void testNoArguments() { var jpackage = new JpackageOperation(); - assertTrue(jpackage.options().isEmpty(), "options not empty"); + assertTrue(jpackage.fileOptions().isEmpty(), "file options not empty"); assertTrue(jpackage.jpackageOptions().isEmpty(), "jpackage options not empty"); assertThrows(ExitStatusException.class, jpackage::execute); } - @Test - void testOptions() { - var jpackage = new JpackageOperation().options("src/test/resources/jlink/options_verbose.txt", - "src/test/resources/jlink/options_version.txt"); - assertDoesNotThrow(jpackage::execute); - } - @Test void testVersion() { - var jpackage = new JpackageOperation().addArgs("--verbose", "--version"); + System.setOut(new PrintStream(outputStreamCaptor)); + var jpackage = new JpackageOperation().toolArgs("--verbose", "--version"); assertDoesNotThrow(jpackage::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); } } From d029bb9b87110cdc9ac36c1ccaf21ec43134c2ce Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 3 Aug 2024 07:47:12 -0700 Subject: [PATCH 16/27] Fixed version parsing in tests --- src/test/java/rife/bld/operations/TestJlinkOperation.java | 4 ++-- src/test/java/rife/bld/operations/TestJmodOperation.java | 4 ++-- src/test/java/rife/bld/operations/TestJpackageOperation.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index 3d385e1..59ec797 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -114,7 +114,7 @@ public class TestJlinkOperation { "src/test/resources/jlink/options_version.txt"); assertDoesNotThrow(jlink::execute); var out = outputStreamCaptor.toString(); - assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); + assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); } @Test @@ -147,6 +147,6 @@ public class TestJlinkOperation { var jlink = new JlinkOperation().toolArgs("--verbose", "--version"); assertDoesNotThrow(jlink::execute); var out = outputStreamCaptor.toString(); - assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); + assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); } } diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index 8b4f520..c1beb88 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -153,7 +153,7 @@ public class TestJmodOperation { var jmod = new JmodOperation().fileOptions("src/test/resources/jlink/options_version.txt"); assertDoesNotThrow(jmod::execute); var out = outputStreamCaptor.toString(); - assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); + assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); } @Test @@ -162,6 +162,6 @@ public class TestJmodOperation { var jmod = new JmodOperation().toolArgs("--version"); assertDoesNotThrow(jmod::execute); var out = outputStreamCaptor.toString(); - assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); + assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); } } diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index 940bef5..054bcd2 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -200,7 +200,7 @@ public class TestJpackageOperation { "src/test/resources/jlink/options_version.txt"); assertDoesNotThrow(jpackage::execute); var out = outputStreamCaptor.toString(); - assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); + assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); } @Test @@ -224,6 +224,6 @@ public class TestJpackageOperation { var jpackage = new JpackageOperation().toolArgs("--verbose", "--version"); assertDoesNotThrow(jpackage::execute); var out = outputStreamCaptor.toString(); - assertTrue(out.matches("\\d+.\\d+.\\d+[\\r\\n]+"), out); + assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); } } From 91640e68cebf7758ffcf66d3920d152d3528e6c1 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 3 Aug 2024 08:01:28 -0700 Subject: [PATCH 17/27] Fixed copyright --- .../rife/bld/operations/AbstractToolProviderOperation.java | 2 +- src/main/java/rife/bld/operations/JlinkOperation.java | 1 - src/main/java/rife/bld/operations/JlinkOptions.java | 2 +- src/main/java/rife/bld/operations/JmodOperation.java | 1 - src/main/java/rife/bld/operations/JmodOptions.java | 2 +- src/main/java/rife/bld/operations/JpackageOperation.java | 1 - src/main/java/rife/bld/operations/JpackageOptions.java | 3 +-- src/test/java/rife/bld/operations/TestJlinkOperation.java | 1 - src/test/java/rife/bld/operations/TestJmodOperation.java | 1 - src/test/java/rife/bld/operations/TestJpackageOperation.java | 1 - 10 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java index c2ec9bc..42fa88f 100644 --- a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java +++ b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com) + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) * Licensed under the Apache License, Version 2.0 (the "License") */ package rife.bld.operations; diff --git a/src/main/java/rife/bld/operations/JlinkOperation.java b/src/main/java/rife/bld/operations/JlinkOperation.java index 0956063..c87aa92 100644 --- a/src/main/java/rife/bld/operations/JlinkOperation.java +++ b/src/main/java/rife/bld/operations/JlinkOperation.java @@ -2,7 +2,6 @@ * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) * Licensed under the Apache License, Version 2.0 (the "License") */ - package rife.bld.operations; import java.util.ArrayList; diff --git a/src/main/java/rife/bld/operations/JlinkOptions.java b/src/main/java/rife/bld/operations/JlinkOptions.java index dd2dc71..89de52e 100644 --- a/src/main/java/rife/bld/operations/JlinkOptions.java +++ b/src/main/java/rife/bld/operations/JlinkOptions.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) * Licensed under the Apache License, Version 2.0 (the "License") */ diff --git a/src/main/java/rife/bld/operations/JmodOperation.java b/src/main/java/rife/bld/operations/JmodOperation.java index 1821598..f75d825 100644 --- a/src/main/java/rife/bld/operations/JmodOperation.java +++ b/src/main/java/rife/bld/operations/JmodOperation.java @@ -2,7 +2,6 @@ * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) * Licensed under the Apache License, Version 2.0 (the "License") */ - package rife.bld.operations; import java.util.ArrayList; diff --git a/src/main/java/rife/bld/operations/JmodOptions.java b/src/main/java/rife/bld/operations/JmodOptions.java index ac36b20..b564595 100644 --- a/src/main/java/rife/bld/operations/JmodOptions.java +++ b/src/main/java/rife/bld/operations/JmodOptions.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) * Licensed under the Apache License, Version 2.0 (the "License") */ diff --git a/src/main/java/rife/bld/operations/JpackageOperation.java b/src/main/java/rife/bld/operations/JpackageOperation.java index ca47e49..6e73375 100644 --- a/src/main/java/rife/bld/operations/JpackageOperation.java +++ b/src/main/java/rife/bld/operations/JpackageOperation.java @@ -2,7 +2,6 @@ * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) * Licensed under the Apache License, Version 2.0 (the "License") */ - package rife.bld.operations; import java.util.ArrayList; diff --git a/src/main/java/rife/bld/operations/JpackageOptions.java b/src/main/java/rife/bld/operations/JpackageOptions.java index 32321fe..74160db 100644 --- a/src/main/java/rife/bld/operations/JpackageOptions.java +++ b/src/main/java/rife/bld/operations/JpackageOptions.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) * Licensed under the Apache License, Version 2.0 (the "License") */ @@ -12,7 +12,6 @@ import java.util.HashMap; * @author Erik C. Thauvin * @since 2.0.2 */ - public class JpackageOptions extends HashMap { /** * URL of the application's home page. diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index 59ec797..cee13ff 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -2,7 +2,6 @@ * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) * Licensed under the Apache License, Version 2.0 (the "License") */ - package rife.bld.operations; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index c1beb88..390ef20 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -2,7 +2,6 @@ * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) * Licensed under the Apache License, Version 2.0 (the "License") */ - package rife.bld.operations; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index 054bcd2..0b28c80 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -2,7 +2,6 @@ * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) * Licensed under the Apache License, Version 2.0 (the "License") */ - package rife.bld.operations; import org.junit.jupiter.api.AfterEach; From 1d615a501cd5699b0a49b7782be29aee8d450ada Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 3 Aug 2024 09:51:09 -0700 Subject: [PATCH 18/27] More operation options cleanups --- .../rife/bld/operations/JlinkOperation.java | 10 --- .../rife/bld/operations/JlinkOptions.java | 87 +++++++++++-------- .../java/rife/bld/operations/JmodOptions.java | 35 +++----- .../rife/bld/operations/ZipCompression.java | 30 ------- .../bld/operations/TestJlinkOperation.java | 8 +- .../bld/operations/TestJmodOperation.java | 1 - .../bld/operations/TestJpackageOperation.java | 7 +- 7 files changed, 73 insertions(+), 105 deletions(-) delete mode 100644 src/main/java/rife/bld/operations/ZipCompression.java diff --git a/src/main/java/rife/bld/operations/JlinkOperation.java b/src/main/java/rife/bld/operations/JlinkOperation.java index c87aa92..0bf7994 100644 --- a/src/main/java/rife/bld/operations/JlinkOperation.java +++ b/src/main/java/rife/bld/operations/JlinkOperation.java @@ -85,14 +85,4 @@ public class JlinkOperation extends AbstractToolProviderOperation fileOptions() { return fileOptions_; } - - /** - * List available plugins. - * - * @return this operation instance - */ - public JlinkOperation listPlugins() { - toolArgs("--list-plugins"); - return this; - } } diff --git a/src/main/java/rife/bld/operations/JlinkOptions.java b/src/main/java/rife/bld/operations/JlinkOptions.java index 89de52e..869c8b6 100644 --- a/src/main/java/rife/bld/operations/JlinkOptions.java +++ b/src/main/java/rife/bld/operations/JlinkOptions.java @@ -15,7 +15,7 @@ import java.util.List; * @since 2.0.2 */ public class JlinkOptions extends HashMap { - /**ranran + /** * All Modules Path. */ @SuppressWarnings("unused") @@ -50,16 +50,12 @@ public class JlinkOptions extends HashMap { } /** - * Compression to use in compressing resources. - *

- * Where {@link ZipCompression#ZIP_0 ZIP_0} provides no compression and {@link ZipCompression#ZIP_9 ZIP_9} provides - * the best compression. - *

Default is {@link ZipCompression#ZIP_6 ZIP_6} + * Enable compression of resources. * - * @param compression the {@link ZipCompression compression} level + * @param compression the {@link CompressionLevel compression} level * @return this map of options */ - public JlinkOptions compress(ZipCompression compression) { + public JlinkOptions compress(CompressionLevel compression) { put("--compress", compression.level); return this; } @@ -106,21 +102,6 @@ public class JlinkOptions extends HashMap { return this; } - /** - * Exclude include header files. - * - * @param noHeaderFiles {@code true} to exclude header files, {@code false} otherwise - * @return this map of options - */ - public JlinkOptions noHeaderFiles(boolean noHeaderFiles) { - if (noHeaderFiles) { - put("--no-header-files"); - } else { - remove("--no-header-files"); - } - return this; - } - /** * Add a launcher command of the given name for the module and the main class. * @@ -159,6 +140,21 @@ public class JlinkOptions extends HashMap { return this; } + /** + * Exclude include header files. + * + * @param noHeaderFiles {@code true} to exclude header files, {@code false} otherwise + * @return this map of options + */ + public JlinkOptions noHeaderFiles(boolean noHeaderFiles) { + if (noHeaderFiles) { + put("--no-header-files"); + } else { + remove("--no-header-files"); + } + return this; + } + /** * Exclude man pages. * @@ -174,16 +170,6 @@ public class JlinkOptions extends HashMap { return this; } - /** - * Associates {@code null} with the specified key in this map. If the map previously contained a mapping for the - * key, the old value is replaced. - * - * @param key key with which the specified value is to be associated - */ - public void put(String key) { - put(key, null); - } - /** * Location of output path. * @@ -195,6 +181,16 @@ public class JlinkOptions extends HashMap { return this; } + /** + * Associates {@code null} with the specified key in this map. If the map previously contained a mapping for the + * key, the old value is replaced. + * + * @param key key with which the specified value is to be associated + */ + public void put(String key) { + put(key, null); + } + /** * Suggest providers that implement the given service types from the module path. * @@ -222,7 +218,7 @@ public class JlinkOptions extends HashMap { } /** - * Strip the native commands. + * Strip native commands. * * @param stripNativeCommands {@code true} to strip, {@code false} otherwise * @return this map of options @@ -286,4 +282,27 @@ public class JlinkOptions extends HashMap { } } + /** + * Resources compression levels. + */ + public enum CompressionLevel { + /** + * Level 0: No compression + */ + NO_COMPRESSION("0"), + /** + * Level 1: Constant string sharing + */ + CONSTANT_STRING_SHARING("1"), + /** + * Level 2: ZIP + */ + ZIP("2"); + + public final String level; + + CompressionLevel(String level) { + this.level = level; + } + } } diff --git a/src/main/java/rife/bld/operations/JmodOptions.java b/src/main/java/rife/bld/operations/JmodOptions.java index b564595..9fa7878 100644 --- a/src/main/java/rife/bld/operations/JmodOptions.java +++ b/src/main/java/rife/bld/operations/JmodOptions.java @@ -38,21 +38,6 @@ public class JmodOptions extends HashMap { return this; } - /** - * Compression to use when creating the JMOD archive. - *

- * Where {@link ZipCompression#ZIP_0 ZIP_0} provides no compression and {@link ZipCompression#ZIP_9 ZIP_9} provides the - * best compression. - *

Default is {@link ZipCompression#ZIP_6 ZIP_6} - * - * @param compression the {@link ZipCompression compression} level - * @return this map of options - */ - public JmodOptions compress(ZipCompression compression) { - put("--compress", compression.level); - return this; - } - /** * Location of user-editable config files * @@ -135,16 +120,6 @@ public class JmodOptions extends HashMap { return this; } - /** - * Associates {@code null} with the specified key in this map. If the map previously contained a mapping for the - * key, the old value is replaced. - * - * @param key key with which the specified value is to be associated - */ - public void put(String key) { - put(key, null); - } - /** * Compute and record hashes to tie a packaged module with modules matching the given regular expression pattern and * depending upon it directly or indirectly. The hashes are recorded in the JMOD file being created, or a JMOD file @@ -235,6 +210,16 @@ public class JmodOptions extends HashMap { return this; } + /** + * Associates {@code null} with the specified key in this map. If the map previously contained a mapping for the + * key, the old value is replaced. + * + * @param key key with which the specified value is to be associated + */ + public void put(String key) { + put(key, null); + } + /** * Target platform. * diff --git a/src/main/java/rife/bld/operations/ZipCompression.java b/src/main/java/rife/bld/operations/ZipCompression.java deleted file mode 100644 index 4d5722a..0000000 --- a/src/main/java/rife/bld/operations/ZipCompression.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) - * Licensed under the Apache License, Version 2.0 (the "License") - */ -package rife.bld.operations; - -/** - * The zip compression levels for jlink and jmod. - * - * @author Erik C. Thauvin - * @since 2.0.2 - */ -public enum ZipCompression { - ZIP_0("zip-0"), - ZIP_1("zip-1"), - ZIP_2("zip-2"), - ZIP_3("zip-3"), - ZIP_4("zip-4"), - ZIP_5("zip-5"), - ZIP_6("zip-6"), - ZIP_7("zip-7"), - ZIP_8("zip-8"), - ZIP_9("zip-9"); - - public final String level; - - ZipCompression(String level) { - this.level = level; - } -} diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index cee13ff..ff76635 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -17,6 +17,7 @@ import java.nio.file.Files; import java.util.HashMap; import static org.junit.jupiter.api.Assertions.*; +import static rife.bld.operations.JlinkOptions.CompressionLevel; public class TestJlinkOperation { private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); @@ -32,7 +33,7 @@ public class TestJlinkOperation { var args = new HashMap(); args.put("--add-modules", "module-1,module-2"); args.put("--bind-services", null); - args.put("--compress", "zip-6"); + args.put("--compress", "2"); args.put("--endian", "big"); args.put("--ignore-signing-information", null); args.put("--launcher", "name=module/mainclass"); @@ -49,7 +50,7 @@ public class TestJlinkOperation { var options = new JlinkOptions() .addModules(args.get("--add-modules").split(",")) .bindServices(true) - .compress(ZipCompression.ZIP_6) + .compress(CompressionLevel.ZIP) .endian(JlinkOptions.Endian.BIG) .ignoreSigningInformation(true) .launcher("name", "module", "mainclass") @@ -80,7 +81,7 @@ public class TestJlinkOperation { var jlink = new JlinkOperation() .disablePlugin("vm") .disablePlugin("system-modules") - .listPlugins(); + .toolArgs("--list-plugins"); assertDoesNotThrow(jlink::execute); var out = outputStreamCaptor.toString(); assertTrue(out.contains("List of available plugins:"), out); @@ -96,6 +97,7 @@ public class TestJlinkOperation { .modulePath("src/test/resources/jlink/build/jmod") .addModules("dev.mccue.tree") .launcher("tree", "dev.mccue.tree", "dev.mccue.tree.Tree") + .compress(CompressionLevel.NO_COMPRESSION) .output(output.getAbsolutePath()); var jlink = new JlinkOperation().jlinkOptions(options); diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index 390ef20..8b6c98e 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -56,7 +56,6 @@ public class TestJmodOperation { var options = new JmodOptions() .classpath(args.get("--class-path")) .cmds(args.get("--cmds")) - .compress(ZipCompression.ZIP_5) .config(args.get("--config")) .date(ZonedDateTime.of(1997, 8, 29, 2, 14, 0, 0, ZoneId.of("America/Los_Angeles"))) .dir(args.get("--dir")) diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index 0b28c80..82c4aaf 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -166,14 +166,17 @@ public class TestJpackageOperation { void testCreatePackage() throws Exception { var tmpdir = Files.createTempDirectory("bld-jpackage-test").toFile(); try { + var jlinkOptions = new JlinkOptions() + .compress(JlinkOptions.CompressionLevel.ZIP) + .stripNativeCommands(true); var options = new JpackageOptions() .input("lib/bld") .name("bld") .mainJar("bld-wrapper.jar") .javaOptions("--enable-preview") .dest(tmpdir.getAbsolutePath()) - .verbose(true); - + .verbose(true) + .jlinkOptions(jlinkOptions); var os = System.getProperty("os.version"); if (os.endsWith("MANJARO")) { options.type(PackageType.DEB); From 750758993d7723cb472db6b91d28a49c95a45ae4 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 3 Aug 2024 10:15:21 -0700 Subject: [PATCH 19/27] Tests cleanup --- src/test/java/rife/bld/operations/TestJmodOperation.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index 8b6c98e..f6bcca8 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -35,7 +35,6 @@ public class TestJmodOperation { var args = new HashMap(); args.put("--class-path", "classpath"); args.put("--cmds", "cmds"); - args.put("--compress", "zip-5"); args.put("--config", "config"); args.put("--date", "1997-08-29T09:14:00Z"); args.put("--dir", "dir"); @@ -119,12 +118,17 @@ public class TestJmodOperation { assertTrue(mod.exists(), "mod does not exist"); jmod.jmodOptions().clear(); + System.setOut(new PrintStream(outputStreamCaptor)); jmod.operationMode(OperationMode.DESCRIBE); assertDoesNotThrow(jmod::execute, "describe mod failed"); + assertTrue(outputStreamCaptor.toString().contains("dev.mccue.tree"), + "missing dev.mccue.tee in:\n" + outputStreamCaptor); jmod.operationMode(OperationMode.LIST); assertDoesNotThrow(jmod::execute, "list mod failed"); + assertTrue(outputStreamCaptor.toString().contains("module-info.class"), + "missing module-info.class in:\n" + outputStreamCaptor); } finally { FileUtils.deleteDirectory(tmpdir); } From e32e17403fcd8a83c9f1b30f37c6b9d88b0c5b63 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sun, 4 Aug 2024 00:39:12 -0700 Subject: [PATCH 20/27] Added support for Java 20-21 specific options --- .../rife/bld/operations/JlinkOptions.java | 17 +++++++++++ .../java/rife/bld/operations/JmodOptions.java | 18 +++++++++++ .../rife/bld/operations/JpackageOptions.java | 10 +++++-- .../rife/bld/operations/ZipCompression.java | 30 +++++++++++++++++++ .../bld/operations/TestJlinkOperation.java | 7 ++++- .../bld/operations/TestJmodOperation.java | 4 +++ 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 src/main/java/rife/bld/operations/ZipCompression.java diff --git a/src/main/java/rife/bld/operations/JlinkOptions.java b/src/main/java/rife/bld/operations/JlinkOptions.java index 869c8b6..eaae145 100644 --- a/src/main/java/rife/bld/operations/JlinkOptions.java +++ b/src/main/java/rife/bld/operations/JlinkOptions.java @@ -49,6 +49,23 @@ public class JlinkOptions extends HashMap { return this; } + /** + * Compression to use in compressing resources. + *

+ * Requires Java 21 or higher. + *

+ * Where {@link ZipCompression#ZIP_0 ZIP_0} provides no compression and {@link ZipCompression#ZIP_9 ZIP_9} provides + * the best compression. + *

Default is {@link ZipCompression#ZIP_6 ZIP_6} + * + * @param compression the {@link ZipCompression compression} level + * @return this map of options + */ + public JlinkOptions compress(ZipCompression compression) { + put("--compress", compression.level); + return this; + } + /** * Enable compression of resources. * diff --git a/src/main/java/rife/bld/operations/JmodOptions.java b/src/main/java/rife/bld/operations/JmodOptions.java index 9fa7878..ca9a183 100644 --- a/src/main/java/rife/bld/operations/JmodOptions.java +++ b/src/main/java/rife/bld/operations/JmodOptions.java @@ -38,6 +38,24 @@ public class JmodOptions extends HashMap { return this; } + /** + * Compression to use when creating the JMOD archive. + *

+ * Requires Java 20 or higher. + *

+ * Where {@link ZipCompression#ZIP_0 ZIP_0} provides no compression and {@link ZipCompression#ZIP_9 ZIP_9} provides the + * best compression. + *

+ * Default is {@link ZipCompression#ZIP_6 ZIP_6} + * + * @param compression the {@link ZipCompression compression} level + * @return this map of options + */ + public JmodOptions compress(ZipCompression compression) { + put("--compress", compression.level); + return this; + } + /** * Location of user-editable config files * diff --git a/src/main/java/rife/bld/operations/JpackageOptions.java b/src/main/java/rife/bld/operations/JpackageOptions.java index 74160db..8702562 100644 --- a/src/main/java/rife/bld/operations/JpackageOptions.java +++ b/src/main/java/rife/bld/operations/JpackageOptions.java @@ -27,8 +27,10 @@ public class JpackageOptions extends HashMap { /** * List of application launchers. *

- * The main application launcher will be built from the command line options. Additional alternative launchers - * can be built using this option, and this option can be used to build multiple additional launchers. + * The main application launcher will be built from the command line options. + *

+ * Additional alternative launchers can be built using this option, and this option can be used to build multiple + * additional launchers. * * @param launcher one or more {@link Launcher} * @return this map of options @@ -58,6 +60,8 @@ public class JpackageOptions extends HashMap { /** * List of paths to files and/or directories to add to the application payload. + *

+ * Requires Java 20 or higher. * * @param additionalContent one or more path * @return this map of options @@ -213,6 +217,8 @@ public class JpackageOptions extends HashMap { /** * Request to create an installer that will register the main application launcher as a background service-type * application. + *

+ * Requires Java 20 or higher. * * @param launcherAsService {@code true} to register the launcher as a service; {@code false} otherwise * @return this map of options diff --git a/src/main/java/rife/bld/operations/ZipCompression.java b/src/main/java/rife/bld/operations/ZipCompression.java new file mode 100644 index 0000000..4d5722a --- /dev/null +++ b/src/main/java/rife/bld/operations/ZipCompression.java @@ -0,0 +1,30 @@ +/** + * Copyright 2024 Erik C. Thauvin (https://erik.thauvin.net/) + * Licensed under the Apache License, Version 2.0 (the "License") + */ +package rife.bld.operations; + +/** + * The zip compression levels for jlink and jmod. + * + * @author Erik C. Thauvin + * @since 2.0.2 + */ +public enum ZipCompression { + ZIP_0("zip-0"), + ZIP_1("zip-1"), + ZIP_2("zip-2"), + ZIP_3("zip-3"), + ZIP_4("zip-4"), + ZIP_5("zip-5"), + ZIP_6("zip-6"), + ZIP_7("zip-7"), + ZIP_8("zip-8"), + ZIP_9("zip-9"); + + public final String level; + + ZipCompression(String level) { + this.level = level; + } +} diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index ff76635..00b9f1c 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -97,8 +97,13 @@ public class TestJlinkOperation { .modulePath("src/test/resources/jlink/build/jmod") .addModules("dev.mccue.tree") .launcher("tree", "dev.mccue.tree", "dev.mccue.tree.Tree") - .compress(CompressionLevel.NO_COMPRESSION) .output(output.getAbsolutePath()); + if (Runtime.version().version().get(0) >= 21) { + options.compress(ZipCompression.ZIP_6); + } else { + options.compress(CompressionLevel.ZIP); + } + var jlink = new JlinkOperation().jlinkOptions(options); assertDoesNotThrow(jlink::execute); diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index f6bcca8..ceda755 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -109,6 +109,10 @@ public class TestJmodOperation { var mod = new File(tmpdir, "dev.mccue.tree.jmod"); var options = new JmodOptions().classpath("src/test/resources/jlink/build/jar/dev.mccue.tree.jar"); + if (Runtime.version().version().get(0) >= 20) { + options.compress(ZipCompression.ZIP_9); + } + var jmod = new JmodOperation() .operationMode(OperationMode.CREATE) .jmodFile(mod.getAbsolutePath()) From 62a324068feba928e08f5366de90e3acf663952e Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sun, 4 Aug 2024 09:06:41 -0700 Subject: [PATCH 21/27] Cleanups --- classes/META-INF/MANIFEST.MF | 3 --- classes/dev/mccue/tree/Tree.class | Bin 604 -> 0 bytes classes/module-info.class | Bin 237 -> 0 bytes .../java/rife/bld/operations/JlinkOptions.java | 6 +++++- 4 files changed, 5 insertions(+), 4 deletions(-) delete mode 100644 classes/META-INF/MANIFEST.MF delete mode 100644 classes/dev/mccue/tree/Tree.class delete mode 100644 classes/module-info.class diff --git a/classes/META-INF/MANIFEST.MF b/classes/META-INF/MANIFEST.MF deleted file mode 100644 index 4512657..0000000 --- a/classes/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Created-By: 17.0.12 (Eclipse Adoptium) - diff --git a/classes/dev/mccue/tree/Tree.class b/classes/dev/mccue/tree/Tree.class deleted file mode 100644 index 77d34f1c431dad0fc0b405e1fcb2182b783158d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 604 zcmZuuTT22#7(L^v?qNjBmWMnV0?F#*?>Omo)AJC7A zzLCJ9Ue3&%Ip6utH}moN_730-2L=+*IFcq(NHgU6_RzLm+wWP|-M(-lhV-fQWpvJ< z)#@FN3`6Nb3@y)bVqw{Xfh(*Fg$6h@9a)$hb0+4o@XN0K^cV?`T!NTPORZ@m8CW-= z^rLnZ3fpUNEHV^k?!*e~mcT#`nu4N<63PsESJ+`Qj3s%k)atES&5uM46=~VT3RW3X zPT&S1Ly^?8A*r$Sdn8;(g=53SCaM(SpKuI(prX1yrLX<9sCO8Wm%)QzSZGOKT*Y2j zgtvCrB_`?FlIqH}`~M4#b`Xb-Xi6p4)x<|C0*-0q1bq~sfkr@@aEneAS{bdW!!g(k zZ5Xx*)isfX^hktCS|tO;W+vcwW9ZMc|EcECv4h=j^~tmmP<(|kL5>RYBNRqh8ewhL XCyyk#WMROhfLRpiw;A?`OJM&CXwP~$ diff --git a/classes/module-info.class b/classes/module-info.class deleted file mode 100644 index 647decb36d5a02653defcfd61f2eb33ecfae1f8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 237 zcmYk0F%E)25Jmq0ihu%%mR`X{Y^-eUOiVn%x~v8TAt2P8%fbVADB}V#I>pSNH$RjA zdOw~3Ht-2fnnhJ27xC?snIMAy2iS$zoZv>XW~mUBWcNbKDU6;49Sd4E!;oOLc6Q{Y zvWy63xMoWht_a@m0nhV9ogIRG$f`ofZJbELaM#69e|xd#;>ypmYyeF~?Muf*2@N`2 WHRl*~ScBC7HpbodZJrVaREQ7YS}~Xa diff --git a/src/main/java/rife/bld/operations/JlinkOptions.java b/src/main/java/rife/bld/operations/JlinkOptions.java index eaae145..cbe71cf 100644 --- a/src/main/java/rife/bld/operations/JlinkOptions.java +++ b/src/main/java/rife/bld/operations/JlinkOptions.java @@ -52,7 +52,7 @@ public class JlinkOptions extends HashMap { /** * Compression to use in compressing resources. *

- * Requires Java 21 or higher. + * Requires Java 21 or higher. Use {@link #compress(CompressionLevel)} for lower versions. *

* Where {@link ZipCompression#ZIP_0 ZIP_0} provides no compression and {@link ZipCompression#ZIP_9 ZIP_9} provides * the best compression. @@ -60,6 +60,7 @@ public class JlinkOptions extends HashMap { * * @param compression the {@link ZipCompression compression} level * @return this map of options + * @see #compress(ZipCompression) */ public JlinkOptions compress(ZipCompression compression) { put("--compress", compression.level); @@ -68,9 +69,12 @@ public class JlinkOptions extends HashMap { /** * Enable compression of resources. + *

+ * Use {@link #compress(ZipCompression)} on Java 21 or higher. * * @param compression the {@link CompressionLevel compression} level * @return this map of options + * @see #compress(CompressionLevel) */ public JlinkOptions compress(CompressionLevel compression) { put("--compress", compression.level); From a06ce8eaaa7909839cc131b0b43162c33409ef33 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sun, 4 Aug 2024 20:16:55 -0700 Subject: [PATCH 22/27] Renamed fileOptions to cmdFiles --- .../rife/bld/operations/JlinkOperation.java | 57 ++++++++++--------- .../rife/bld/operations/JmodOperation.java | 44 +++++++------- .../bld/operations/TestJlinkOperation.java | 6 +- .../bld/operations/TestJmodOperation.java | 20 +++---- 4 files changed, 64 insertions(+), 63 deletions(-) diff --git a/src/main/java/rife/bld/operations/JlinkOperation.java b/src/main/java/rife/bld/operations/JlinkOperation.java index 0bf7994..31aafc7 100644 --- a/src/main/java/rife/bld/operations/JlinkOperation.java +++ b/src/main/java/rife/bld/operations/JlinkOperation.java @@ -15,14 +15,35 @@ import java.util.Map; * @since 2.0.2 */ public class JlinkOperation extends AbstractToolProviderOperation { + private final List cmdFiles_ = new ArrayList<>(); private final List disabledPlugins_ = new ArrayList<>(); private final JlinkOptions jlinkOptions_ = new JlinkOptions(); - private final List fileOptions_ = new ArrayList<>(); public JlinkOperation() { super("jlink"); } + + /** + * Read options and/or mode from file(s). + * + * @param file one or more file + * @return this operation instance + */ + public JlinkOperation cmdFiles(String... file) { + cmdFiles_.addAll(List.of(file)); + return this; + } + + /** + * Retrieves the list of files containing options or mode. + * + * @return the list of files + */ + public List cmdFiles() { + return cmdFiles_; + } + /** * Disable the plugin mentioned. * @@ -36,23 +57,12 @@ public class JlinkOperation extends AbstractToolProviderOperation toolArgs("--disable-plugin", plugin)); toolArgs(jlinkOptions_); super.execute(); } - /** - * Retrieves the list of options for the jlink tool. - *

- * This is a modifiable list that can be retrieved and changed. - * - * @return the map of jlink options - */ - public JlinkOptions jlinkOptions() { - return jlinkOptions_; - } - /** * Provides a list of options to provide to the jlink tool. *

@@ -67,22 +77,13 @@ public class JlinkOperation extends AbstractToolProviderOperation + * This is a modifiable list that can be retrieved and changed. * - * @param file one or more file - * @return this operation instance + * @return the map of jlink options */ - public JlinkOperation fileOptions(String... file) { - fileOptions_.addAll(List.of(file)); - return this; - } - - /** - * Retrieves the list of files containing options or mode. - * - * @return the list of files - */ - public List fileOptions() { - return fileOptions_; + public JlinkOptions jlinkOptions() { + return jlinkOptions_; } } diff --git a/src/main/java/rife/bld/operations/JmodOperation.java b/src/main/java/rife/bld/operations/JmodOperation.java index f75d825..85f11d1 100644 --- a/src/main/java/rife/bld/operations/JmodOperation.java +++ b/src/main/java/rife/bld/operations/JmodOperation.java @@ -15,7 +15,7 @@ import java.util.Map; * @since 2.0.2 */ public class JmodOperation extends AbstractToolProviderOperation { - private final List fileOptions_ = new ArrayList<>(); + private final List cmdFiles = new ArrayList<>(); private final JmodOptions jmodOptions_ = new JmodOptions(); private String jmodFile_; private OperationMode operationMode_; @@ -24,13 +24,33 @@ public class JmodOperation extends AbstractToolProviderOperation super("jmod"); } + /** + * Retrieves the list of files containing options or mode. + * + * @return the list of files + */ + public List cmdFiles() { + return cmdFiles; + } + + /** + * Read options and/or mode from file(s). + * + * @param file one or more file + * @return this operation instance + */ + public JmodOperation cmdFiles(String... file) { + cmdFiles.addAll(List.of(file)); + return this; + } + @Override public void execute() throws Exception { if (operationMode_ != null) { toolArgs(operationMode_.mode); } - toolArgsFromFile(fileOptions_); + toolArgsFromFile(cmdFiles); toolArgs(jmodOptions_); if (jmodFile_ != null) { @@ -40,26 +60,6 @@ public class JmodOperation extends AbstractToolProviderOperation super.execute(); } - /** - * Retrieves the list of files containing options or mode. - * - * @return the list of files - */ - public List fileOptions() { - return fileOptions_; - } - - /** - * Read options and/or mode from a file. - * - * @param file one or more file - * @return this operation instance - */ - public JmodOperation fileOptions(String... file) { - fileOptions_.addAll(List.of(file)); - return this; - } - /** * Retrieves the name of the JMOD file to create or from which to retrieve information. * diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index 00b9f1c..e8bea79 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -116,7 +116,7 @@ public class TestJlinkOperation { @Test void testFileOptions() { System.setOut(new PrintStream(outputStreamCaptor)); - var jlink = new JlinkOperation().fileOptions("src/test/resources/jlink/options_verbose.txt", + var jlink = new JlinkOperation().cmdFiles("src/test/resources/jlink/options_verbose.txt", "src/test/resources/jlink/options_version.txt"); assertDoesNotThrow(jlink::execute); var out = outputStreamCaptor.toString(); @@ -134,14 +134,14 @@ public class TestJlinkOperation { void testNoArguments() { var jlink = new JlinkOperation(); assertTrue(jlink.jlinkOptions().isEmpty(), "jlink options not empty"); - assertTrue(jlink.fileOptions().isEmpty(), "file options not empty"); + assertTrue(jlink.cmdFiles().isEmpty(), "file options not empty"); assertThrows(ExitStatusException.class, jlink::execute); } @Test void testParseOptions() { System.setOut(new PrintStream(outputStreamCaptor)); - var jlink = new JlinkOperation().fileOptions("src/test/resources/jlink/options_jlink.txt"); + var jlink = new JlinkOperation().cmdFiles("src/test/resources/jlink/options_jlink.txt"); assertDoesNotThrow(jlink::execute); var out = outputStreamCaptor.toString(); assertTrue(out.contains("List of available plugins:"), out); diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index ceda755..e3cfb94 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -138,6 +138,15 @@ public class TestJmodOperation { } } + @Test + void testFileOptions() { + System.setOut(new PrintStream(outputStreamCaptor)); + var jmod = new JmodOperation().cmdFiles("src/test/resources/jlink/options_version.txt"); + assertDoesNotThrow(jmod::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); + } + @Test void testHelp() { var jmod = new JmodOperation().toolArgs("--help-extra"); @@ -148,20 +157,11 @@ public class TestJmodOperation { @Test void testNoArguments() { var jmod = new JmodOperation(); - assertTrue(jmod.fileOptions().isEmpty(), "file options not empty"); + assertTrue(jmod.cmdFiles().isEmpty(), "file options not empty"); assertTrue(jmod.jmodOptions().isEmpty(), "jmod options not empty"); assertThrows(ExitStatusException.class, jmod::execute); } - @Test - void testFileOptions() { - System.setOut(new PrintStream(outputStreamCaptor)); - var jmod = new JmodOperation().fileOptions("src/test/resources/jlink/options_version.txt"); - assertDoesNotThrow(jmod::execute); - var out = outputStreamCaptor.toString(); - assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); - } - @Test void testVersion() { System.setOut(new PrintStream(outputStreamCaptor)); From d42d2d6fa0f7de816f2d7b140e7edfa709b2be0c Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sun, 4 Aug 2024 20:17:26 -0700 Subject: [PATCH 23/27] Added a command line tokenizer --- .../AbstractToolProviderOperation.java | 150 ++++++++++++++---- src/test/resources/jlink/options_jlink.txt | 6 +- 2 files changed, 119 insertions(+), 37 deletions(-) diff --git a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java index 42fa88f..c499574 100644 --- a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java +++ b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java @@ -6,12 +6,15 @@ package rife.bld.operations; import rife.bld.operations.exceptions.ExitStatusException; -import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Reader; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Scanner; import java.util.spi.ToolProvider; /** @@ -73,23 +76,6 @@ public abstract class AbstractToolProviderOperation args) { - args.forEach((k, v) -> { - toolArgs_.add(k); - if (v != null && !v.isEmpty()) { - toolArgs_.add(v); - } - }); - return (T) this; - } - /** * Adds arguments to pass to the tool. * @@ -119,28 +105,122 @@ public abstract class AbstractToolProviderOperation files) throws FileNotFoundException { - var list = new ArrayList(); + public T toolArgsFromFile(List files) throws IOException { + var args = new ArrayList(); - for (var option : files) { - try (var scanner = new Scanner(new File(option))) { - while (scanner.hasNext()) { - var splitLine = scanner.nextLine().split("--"); - for (String args : splitLine) { - if (!args.isBlank()) { - var splitArgs = args.split(" ", 2); - list.add("--" + splitArgs[0]); - if (splitArgs.length > 1 && !splitArgs[1].isBlank()) { - list.add(splitArgs[1]); - } - } - } + for (var file : files) { + try (var reader = Files.newBufferedReader(Paths.get(file), Charset.defaultCharset())) { + var tokenizer = new CommandLineTokenizer(reader); + String token; + while ((token = tokenizer.nextToken()) != null) { + args.add(token); } } } - toolArgs(list); + toolArgs(args); return (T) this; } + + /** + * Adds arguments to pass to the tool. + * + * @param args the argument-value pairs to add + * @return this operation + */ + @SuppressWarnings({"unchecked", "UnusedReturnValue"}) + protected T toolArgs(Map args) { + args.forEach((k, v) -> { + toolArgs_.add(k); + if (v != null && !v.isEmpty()) { + toolArgs_.add(v); + } + }); + return (T) this; + } + + /** + * Tokenize command line arguments. + * + *

    + *
  • Arguments containing spaces should be quoted
  • + *
  • Escape sequences and comments are supported
  • + *
+ */ + public static class CommandLineTokenizer { + private final StringBuilder buf_ = new StringBuilder(); + private final Reader input_; + private int ch_; + + public CommandLineTokenizer(Reader input) throws IOException { + input_ = input; + ch_ = input.read(); + } + + public String nextToken() throws IOException { + skipWhitespaceOrComments(); + if (ch_ == -1) { + return null; + } + + buf_.setLength(0); // reset buffer + + char quote = 0; + while (ch_ != -1) { + if (Character.isWhitespace(ch_)) { // whitespaces + if (quote == 0) { + break; + } + buf_.append((char) ch_); + } else if (ch_ == '\'' || ch_ == '"') { // quotes + if (quote == 0) { + quote = (char) ch_; + } else if (quote == ch_) { + quote = 0; + } else { + buf_.append((char) ch_); + } + } else if (ch_ == '\\') { // escaped + ch_ = input_.read(); + buf_.append(handleEscapeSequence()); + } else { + buf_.append((char) ch_); + } + + ch_ = input_.read(); + } + return buf_.toString(); + } + + private char handleEscapeSequence() { + if (ch_ == -1) { + return '\\'; + } + + return switch (ch_) { + case 'n' -> '\n'; + case 'r' -> '\r'; + case 't' -> '\t'; + case 'f' -> '\f'; + default -> (char) ch_; + }; + } + + + private void skipWhitespaceOrComments() throws IOException { + while (ch_ != -1) { + if (Character.isWhitespace(ch_)) { // Skip whitespaces + ch_ = input_.read(); + } else if (ch_ == '#') { + // Skip the entire comment until a new line or end of input + do { + ch_ = input_.read(); + } while (ch_ != -1 && ch_ != '\n' && ch_ != '\r'); + } else { + return; + } + } + } + } } diff --git a/src/test/resources/jlink/options_jlink.txt b/src/test/resources/jlink/options_jlink.txt index f991ca7..0d15982 100644 --- a/src/test/resources/jlink/options_jlink.txt +++ b/src/test/resources/jlink/options_jlink.txt @@ -1,2 +1,4 @@ - --verbose --version - --list-plugins + --verbose --version #foo + --module-path "foo bar" --list-plugins +# bar + From d72e6ebc2e57f1c0cb3ff6800240ec188bf243ab Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Mon, 5 Aug 2024 10:25:41 -0700 Subject: [PATCH 24/27] Truncate jmod ISO date to seconds --- src/main/java/rife/bld/operations/JmodOptions.java | 3 ++- src/test/java/rife/bld/operations/TestJmodOperation.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/rife/bld/operations/JmodOptions.java b/src/main/java/rife/bld/operations/JmodOptions.java index ca9a183..3510655 100644 --- a/src/main/java/rife/bld/operations/JmodOptions.java +++ b/src/main/java/rife/bld/operations/JmodOptions.java @@ -6,6 +6,7 @@ package rife.bld.operations; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.HashMap; @@ -74,7 +75,7 @@ public class JmodOptions extends HashMap { * @return this map of options */ public JmodOptions date(ZonedDateTime date) { - put("--date", date.format(DateTimeFormatter.ISO_INSTANT)); + put("--date", date.truncatedTo(ChronoUnit.SECONDS).format(DateTimeFormatter.ISO_INSTANT)); return this; } diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index e3cfb94..e62b3b6 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -56,7 +56,7 @@ public class TestJmodOperation { .classpath(args.get("--class-path")) .cmds(args.get("--cmds")) .config(args.get("--config")) - .date(ZonedDateTime.of(1997, 8, 29, 2, 14, 0, 0, ZoneId.of("America/Los_Angeles"))) + .date(ZonedDateTime.of(1997, 8, 29, 2, 14, 0, 1, ZoneId.of("America/Los_Angeles"))) .dir(args.get("--dir")) .doNotResolveByDefault(true) .dryRun(true) From 0382444c0cce1e72189042c18dea5fbc1faf8779 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Mon, 5 Aug 2024 10:40:42 -0700 Subject: [PATCH 25/27] Added more command files tests --- .../AbstractToolProviderOperation.java | 4 +- .../bld/operations/JpackageOperation.java | 12 +++--- .../bld/operations/TestJlinkOperation.java | 38 +++++++++---------- .../bld/operations/TestJmodOperation.java | 36 +++++++++++++----- .../bld/operations/TestJpackageOperation.java | 4 +- src/test/resources/jlink/options_jlink.txt | 7 ++-- src/test/resources/jlink/options_jmod.txt | 3 ++ 7 files changed, 63 insertions(+), 41 deletions(-) create mode 100644 src/test/resources/jlink/options_jmod.txt diff --git a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java index c499574..1344daa 100644 --- a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java +++ b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java @@ -159,7 +159,7 @@ public abstract class AbstractToolProviderOperation { - private final List fileOptions_ = new ArrayList<>(); + private final List cmdFiles_ = new ArrayList<>(); private final JpackageOptions jpackageOptions_ = new JpackageOptions(); public JpackageOperation() { @@ -24,7 +24,7 @@ public class JpackageOperation extends AbstractToolProviderOperation '@' + opt).toList()); + toolArgs(cmdFiles_.stream().map(opt -> '@' + opt).toList()); toolArgs(jpackageOptions_); super.execute(); } @@ -35,17 +35,17 @@ public class JpackageOperation extends AbstractToolProviderOperation fileOptions() { - return fileOptions_; + return cmdFiles_; } /** - * Read options and/or mode from a file. + * Read options and/or mode from file(s). * * @param file one or more file * @return this operation instance */ - public JpackageOperation fileOptions(String... file) { - fileOptions_.addAll(List.of(file)); + public JpackageOperation cmdFiles(String... file) { + cmdFiles_.addAll(List.of(file)); return this; } diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index e8bea79..9baef3e 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -75,6 +75,25 @@ public class TestJlinkOperation { assertEquals("name-2=module-2", options.get("--launcher"), "incorrect launcher"); } + @Test + void testCmdFiles() { + System.setOut(new PrintStream(outputStreamCaptor)); + var jlink = new JlinkOperation().cmdFiles("src/test/resources/jlink/options_jlink.txt"); + assertDoesNotThrow(jlink::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.contains("List of available plugins:"), out); + } + + @Test + void testCmdFilesMulti() { + System.setOut(new PrintStream(outputStreamCaptor)); + var jlink = new JlinkOperation().cmdFiles("src/test/resources/jlink/options_verbose.txt", + "src/test/resources/jlink/options_version.txt"); + assertDoesNotThrow(jlink::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); + } + @Test void testDisablePlugin() { System.setOut(new PrintStream(outputStreamCaptor)); @@ -113,16 +132,6 @@ public class TestJlinkOperation { } } - @Test - void testFileOptions() { - System.setOut(new PrintStream(outputStreamCaptor)); - var jlink = new JlinkOperation().cmdFiles("src/test/resources/jlink/options_verbose.txt", - "src/test/resources/jlink/options_version.txt"); - assertDoesNotThrow(jlink::execute); - var out = outputStreamCaptor.toString(); - assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); - } - @Test void testHelp() { var jlink = new JlinkOperation().toolArgs("--help"); @@ -138,15 +147,6 @@ public class TestJlinkOperation { assertThrows(ExitStatusException.class, jlink::execute); } - @Test - void testParseOptions() { - System.setOut(new PrintStream(outputStreamCaptor)); - var jlink = new JlinkOperation().cmdFiles("src/test/resources/jlink/options_jlink.txt"); - assertDoesNotThrow(jlink::execute); - var out = outputStreamCaptor.toString(); - assertTrue(out.contains("List of available plugins:"), out); - } - @Test void testVersion() { System.setOut(new PrintStream(outputStreamCaptor)); diff --git a/src/test/java/rife/bld/operations/TestJmodOperation.java b/src/test/java/rife/bld/operations/TestJmodOperation.java index e62b3b6..ac68b0d 100644 --- a/src/test/java/rife/bld/operations/TestJmodOperation.java +++ b/src/test/java/rife/bld/operations/TestJmodOperation.java @@ -81,6 +81,32 @@ public class TestJmodOperation { } } + @Test + void testCmdFiles() { + System.setOut(new PrintStream(outputStreamCaptor)); + var jmod = new JmodOperation().cmdFiles("src/test/resources/jlink/options_version.txt"); + assertDoesNotThrow(jmod::execute); + var out = outputStreamCaptor.toString(); + assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); + } + + @Test + void testCmdFilesCreate() throws IOException { + var tmpdir = Files.createTempDirectory("bld-jmod-test").toFile(); + try { + var mod = new File(tmpdir, "dev.mccue.tree.jmod"); + + var jmod = new JmodOperation() + .cmdFiles("src/test/resources/jlink/options_jmod.txt") + .jmodFile(mod.getAbsolutePath()); + + assertDoesNotThrow(jmod::execute); + assertTrue(mod.exists(), "mod does not exist"); + } finally { + FileUtils.deleteDirectory(tmpdir); + } + } + @Test void testCreate() throws IOException { var tmpdir = Files.createTempDirectory("bld-jmod-test").toFile(); @@ -88,6 +114,7 @@ public class TestJmodOperation { var mod = new File(tmpdir, "dev.mccue.tree.jmod"); var options = new JmodOptions() + .date(ZonedDateTime.now()) .legalNotices("src/test/resources/jlink/dev.mccue.apple/legal") .classpath("src/test/resources/jlink/build/jar/dev.mccue.apple.jar"); var jmod = new JmodOperation() @@ -138,15 +165,6 @@ public class TestJmodOperation { } } - @Test - void testFileOptions() { - System.setOut(new PrintStream(outputStreamCaptor)); - var jmod = new JmodOperation().cmdFiles("src/test/resources/jlink/options_version.txt"); - assertDoesNotThrow(jmod::execute); - var out = outputStreamCaptor.toString(); - assertTrue(out.matches("[\\d.]+[\\r\\n]+"), out); - } - @Test void testHelp() { var jmod = new JmodOperation().toolArgs("--help-extra"); diff --git a/src/test/java/rife/bld/operations/TestJpackageOperation.java b/src/test/java/rife/bld/operations/TestJpackageOperation.java index 82c4aaf..35657b0 100644 --- a/src/test/java/rife/bld/operations/TestJpackageOperation.java +++ b/src/test/java/rife/bld/operations/TestJpackageOperation.java @@ -196,9 +196,9 @@ public class TestJpackageOperation { } @Test - void testFileOptions() { + void testCmdFiles() { System.setOut(new PrintStream(outputStreamCaptor)); - var jpackage = new JpackageOperation().fileOptions("src/test/resources/jlink/options_verbose.txt", + var jpackage = new JpackageOperation().cmdFiles("src/test/resources/jlink/options_verbose.txt", "src/test/resources/jlink/options_version.txt"); assertDoesNotThrow(jpackage::execute); var out = outputStreamCaptor.toString(); diff --git a/src/test/resources/jlink/options_jlink.txt b/src/test/resources/jlink/options_jlink.txt index 0d15982..1c35a35 100644 --- a/src/test/resources/jlink/options_jlink.txt +++ b/src/test/resources/jlink/options_jlink.txt @@ -1,4 +1,5 @@ - --verbose --version #foo - --module-path "foo bar" --list-plugins -# bar + --verbose --version #--foo + --module-path "\'foo\' \"bar\" --bar" --list-plugins +--output foo --bind-services +# bar \ No newline at end of file diff --git a/src/test/resources/jlink/options_jmod.txt b/src/test/resources/jlink/options_jmod.txt new file mode 100644 index 0000000..81caa7e --- /dev/null +++ b/src/test/resources/jlink/options_jmod.txt @@ -0,0 +1,3 @@ +create +--legal-notices src/test/resources/jlink/dev.mccue.apple/legal +--class-path src/test/resources/jlink/build/jar/dev.mccue.apple.jar \ No newline at end of file From c59d61f8c1d3957cd1a6263157184a6b93c96883 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Mon, 5 Aug 2024 14:52:18 -0700 Subject: [PATCH 26/27] Added command file and test for Windows --- src/test/java/rife/bld/operations/TestJlinkOperation.java | 7 ++++++- src/test/resources/jlink/options_jlink.txt | 2 +- src/test/resources/jlink/options_jlink_win.txt | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 src/test/resources/jlink/options_jlink_win.txt diff --git a/src/test/java/rife/bld/operations/TestJlinkOperation.java b/src/test/java/rife/bld/operations/TestJlinkOperation.java index 9baef3e..1078903 100644 --- a/src/test/java/rife/bld/operations/TestJlinkOperation.java +++ b/src/test/java/rife/bld/operations/TestJlinkOperation.java @@ -78,7 +78,12 @@ public class TestJlinkOperation { @Test void testCmdFiles() { System.setOut(new PrintStream(outputStreamCaptor)); - var jlink = new JlinkOperation().cmdFiles("src/test/resources/jlink/options_jlink.txt"); + final JlinkOperation jlink; + if (System.getProperty("os.name").startsWith("Windows")) { + jlink = new JlinkOperation().cmdFiles("src/test/resources/jlink/options_jlink_win.txt"); + } else { + jlink = new JlinkOperation().cmdFiles("src/test/resources/jlink/options_jlink.txt"); + } assertDoesNotThrow(jlink::execute); var out = outputStreamCaptor.toString(); assertTrue(out.contains("List of available plugins:"), out); diff --git a/src/test/resources/jlink/options_jlink.txt b/src/test/resources/jlink/options_jlink.txt index 1c35a35..64cd9e6 100644 --- a/src/test/resources/jlink/options_jlink.txt +++ b/src/test/resources/jlink/options_jlink.txt @@ -1,5 +1,5 @@ --verbose --version #--foo - --module-path "\'foo\' \"bar\" --bar" --list-plugins + --module-path "\'foo --bar\' \"bar --foo\" --bar" --list-plugins --output foo --bind-services # bar \ No newline at end of file diff --git a/src/test/resources/jlink/options_jlink_win.txt b/src/test/resources/jlink/options_jlink_win.txt new file mode 100644 index 0000000..e47aa53 --- /dev/null +++ b/src/test/resources/jlink/options_jlink_win.txt @@ -0,0 +1,5 @@ + --verbose --version #--foo + --module-path "\'foo --bar\' --bar" --list-plugins +--output foo --bind-services + +# bar \ No newline at end of file From 3bd17e224bc22b74ea2908dd8dc158f46c948574 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 9 Aug 2024 14:16:10 -0700 Subject: [PATCH 27/27] Improved command line tokenizer --- .../AbstractToolProviderOperation.java | 22 ++++++------------- .../bld/operations/TestJlinkOperation.java | 2 +- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java index 1344daa..b6889ba 100644 --- a/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java +++ b/src/main/java/rife/bld/operations/AbstractToolProviderOperation.java @@ -168,15 +168,10 @@ public abstract class AbstractToolProviderOperation '\\'; case 'n' -> '\n'; case 'r' -> '\r'; case 't' -> '\t'; @@ -207,7 +200,6 @@ public abstract class AbstractToolProviderOperation