org.panteleyev.jpackage.JPackageMojo Maven / Gradle / Ivy
/*
Copyright (c) Petr Panteleyev. All rights reserved.
Licensed under the BSD license. See LICENSE file in the project root for full license information.
*/
package org.panteleyev.jpackage;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.panteleyev.jpackage.OsUtil.isLinux;
import static org.panteleyev.jpackage.OsUtil.isMac;
import static org.panteleyev.jpackage.OsUtil.isWindows;
import static org.panteleyev.jpackage.StringUtil.escape;
/**
* Generates application package.
* Each plugin parameter defines jpackage
option.
* For detailed information about these options please refer to
* Packaging Tool User's Guide
*/
@Mojo(name = JPackageMojo.GOAL, defaultPhase = LifecyclePhase.NONE)
public class JPackageMojo extends AbstractMojo {
public static final String GOAL = "jpackage";
private static final String TOOLCHAIN = "jdk";
private static final String EXECUTABLE = "jpackage";
private static final String DRY_RUN_PROPERTY = "jpackage.dryRun";
@Component
private ToolchainManager toolchainManager;
@Parameter(defaultValue = "${session}", required = true, readonly = true)
private MavenSession session;
/**
* --verbose
*
* @since 0.0.4
*/
@Parameter
private boolean verbose;
/**
* --type <type>
*
* Possible values:
*
*
* Plugin JPackage
*
* APP_IMAGE app-image
* DMG dmg
* PKG pkg
* EXE exe
* MSI msi
* DEB deb
*
*
* @since 0.0.1
*/
@Parameter
private ImageType type;
/**
* --name <name>
*
* @since 0.0.1
*/
@Parameter(defaultValue = "${project.name}")
private String name;
/**
* --app-version <version>
*
* @since 0.0.1
*/
@Parameter(defaultValue = "${project.version}")
private String appVersion;
/**
* --vendor <vendor string>
*
* @since 0.0.1
*/
@Parameter
private String vendor;
/**
* --icon <icon file path>
*
* @since 0.0.1
*/
@Parameter
private File icon;
/**
* --runtime-image <file path>
*
* @since 0.0.1
*/
@Parameter
private File runtimeImage;
/**
* --input <input path>
*
* @since 0.0.1
*/
@Parameter
private File input;
/**
* --install-dir <file path>
*
* @since 0.0.4
*/
@Parameter
private File installDir;
/**
* --resource-dir <resource dir path>
*
* @since 1.1.0
*/
@Parameter
private File resourceDir;
/**
* --dest <destination path>
*
* @since 0.0.1
*/
@Parameter
private File destination;
/**
* --module <module name>[/<main class>]
*
* @since 0.0.1
*/
@Parameter
private String module;
/**
* --main-class <class name>
*
* @since 0.0.1
*/
@Parameter
private String mainClass;
/**
* --main-jar <main jar file>
*
* @since 0.0.1
*/
@Parameter
private String mainJar;
/**
* --temp <temp dir path>
*
* @since 1.1.0
*/
@Parameter
private File temp;
/**
* --copyright <copyright string>
*
* @since 0.0.1
*/
@Parameter
private String copyright;
/**
* --description <description string>
*
* @since 0.0.1
*/
@Parameter
private String description;
/**
* Each module path is specified by a separate <modulePath> parameter.
* Example:
*
* <modulePaths>
* <modulePath>target/jmods</modulePath>
* </modulePaths>
*
*
*
* @since 1.4.0
*/
@Parameter
private List modulePaths;
/**
* --java-options <JVM option>
*
* @since 0.0.1
*/
@Parameter
private List javaOptions;
/**
* --arguments <main class arguments>
*
* @since 0.0.4
*/
@Parameter
private List arguments;
/**
* --license-file <license file path>
*
* @since 1.3.0
*/
@Parameter
private File licenseFile;
/**
* --file-associations <file association property file>
*
* Each property file is specified by a separate <fileAssociation> parameter.
* Example:
*
* <fileAssociations>
* <fileAssociation>src/properties/java.properties</fileAssociation>
* <fileAssociation>src/properties/cpp.properties</fileAssociation>
* </fileAssociations>
*
*
*
* @since 1.3.0
*/
@Parameter
private List fileAssociations;
/**
* --add-launcher <name>=<file>
*
* Application launchers specified by one
*
* <launcher>
* <name>name-of-the-launcher</name>
* <file>/path/to/launcher.properties</file>
* </launcher>
*
*
* element for each launcher.
*
* @since 1.3.0
*/
@Parameter
private List launchers;
/**
* --add-modules <module>[,<module>]
*
* @since 1.4.0
*/
@Parameter
private List addModules;
/**
* --app-image <path to application image>
*
* @since 1.5.0
*/
@Parameter
private File appImage;
/**
* Additional jpackage options not covered by dedicated plugin parameters.
*
* Example:
*
* <additionalOptions>
* <option>--jlink-options</option>
* <option>--bind-services</option>
* </additionalOptions>
*
*
*
* @since 1.5.0
*/
@Parameter
private List additionalOptions;
// Windows specific parameters
/**
* --win-menu
*
* @since 0.0.1
*/
@Parameter
private boolean winMenu;
/**
* --win-dir-chooser
*
* @since 0.0.1
*/
@Parameter
private boolean winDirChooser;
/**
* --win-upgrade-uuid <id string>
*
* @since 0.0.1
*/
@Parameter
private String winUpgradeUuid;
/**
* --win-menu-group <menu group name>
*
* @since 0.0.1
*/
@Parameter
private String winMenuGroup;
/**
* --win-shortcut
*
* @since 0.0.1
*/
@Parameter
private boolean winShortcut;
/**
* --win-per-user-install
*
* @since 0.0.1
*/
@Parameter
private boolean winPerUserInstall;
/**
* --win-console
*
* @since 1.3.0
*/
@Parameter
private boolean winConsole;
// OS X specific parameters
/**
* --mac-package-identifier <ID string>
*
* @since 0.0.2
*/
@Parameter
private String macPackageIdentifier;
/**
* --mac-package-name <name string>
*
* @since 0.0.2
*/
@Parameter
private String macPackageName;
/**
* --mac-package-signing-prefix <prefix string>
*
* @since 0.0.2
*/
@Parameter
private String macPackageSigningPrefix;
/**
* --mac-sign
*
* @since 0.0.2
*/
@Parameter
private boolean macSign;
/**
* --mac-signing-keychain <file path>
*
* @since 0.0.2
*/
@Parameter
private File macSigningKeychain;
/**
* --mac-signing-key-user-name <team name>
*
* @since 0.0.2
*/
@Parameter
private String macSigningKeyUserName;
// Linux specific parameters
/**
* --linux-package-name <package name>
*
* @since 0.0.3
*/
@Parameter
private String linuxPackageName;
/**
* --linux-deb-maintainer <email address>
*
* @since 0.0.3
*/
@Parameter
private String linuxDebMaintainer;
/**
* --linux-menu-group <menu-group-name>
*
* @since 0.0.3
*/
@Parameter
private String linuxMenuGroup;
/**
* --linux-rpm-license-type <type string>
*
* @since 0.0.3
*/
@Parameter
private String linuxRpmLicenseType;
/**
* --linux-app-release <release value>
*
* @since 0.0.3
*/
@Parameter
private String linuxAppRelease;
/**
* --linux-app-category <category value>
*
* @since 0.0.3
*/
@Parameter
private String linuxAppCategory;
/**
* --linux-shortcut
*
* @since 0.0.3
*/
@Parameter
private boolean linuxShortcut;
public void execute() throws MojoExecutionException, MojoFailureException {
Toolchain tc = toolchainManager.getToolchainFromBuildContext(TOOLCHAIN, session);
if (tc != null) {
getLog().info("Toolchain in jpackage-maven-plugin: " + tc);
}
String executable = getJPackageExecutable(tc)
.orElseThrow(() -> new MojoExecutionException("Failed to find " + EXECUTABLE));
getLog().info("Using: " + executable);
List parameters = new ArrayList<>();
parameters.add(executable.contains(" ") ? ("\"" + executable + "\"") : executable);
buildParameters(parameters);
boolean dryRun = "true".equalsIgnoreCase(System.getProperty(DRY_RUN_PROPERTY, "false"));
if (dryRun) {
getLog().warn("Dry-run mode, not executing " + EXECUTABLE);
} else {
try {
execute(parameters);
} catch (Exception ex) {
throw new MojoExecutionException(ex.getMessage(), ex);
}
}
}
private Optional getJPackageFromJdkHome(String jdkHome) {
if (jdkHome == null || jdkHome.isEmpty()) {
return Optional.empty();
}
getLog().debug("Looking for " + EXECUTABLE + " in " + jdkHome);
String executable = jdkHome + File.separator + "bin" + File.separator + EXECUTABLE;
if (isWindows()) {
executable = executable + ".exe";
}
if (new File(executable).exists()) {
return Optional.of(executable);
} else {
getLog().warn("File " + executable + " does not exist");
return Optional.empty();
}
}
private Optional getJPackageFromToolchain(Toolchain tc) {
if (tc == null) {
return Optional.empty();
}
String executable = tc.findTool(EXECUTABLE);
if (executable == null) {
getLog().warn(EXECUTABLE + " is not part of configured toolchain");
}
return Optional.ofNullable(executable);
}
private Optional getJPackageExecutable(Toolchain tc) {
Optional executable = getJPackageFromToolchain(tc);
return executable.isPresent() ?
executable : getJPackageFromJdkHome(System.getProperty("java.home"));
}
private void execute(List parameters) throws Exception {
Process process = new ProcessBuilder()
.redirectErrorStream(true)
.command(parameters)
.start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
getLog().info(line);
}
}
int status = process.waitFor();
if (status != 0) {
throw new MojoExecutionException("Error while executing " + EXECUTABLE);
}
}
private void buildParameters(List parameters) throws MojoFailureException {
getLog().info("jpackage options:");
addMandatoryParameter(parameters, "--name", name);
addMandatoryParameter(parameters, "--dest", destination);
addParameter(parameters, "--verbose", verbose);
addParameter(parameters, type);
addParameter(parameters, "--app-version", appVersion);
addParameter(parameters, "--copyright", copyright);
addParameter(parameters, "--description", description);
addParameter(parameters, "--runtime-image", runtimeImage, true);
addParameter(parameters, "--input", input, true);
addParameter(parameters, "--install-dir", installDir);
addParameter(parameters, "--resource-dir", resourceDir, true);
addParameter(parameters, "--vendor", vendor);
addParameter(parameters, "--module", module);
addParameter(parameters, "--main-class", mainClass);
addParameter(parameters, "--main-jar", mainJar);
addParameter(parameters, "--temp", temp);
addParameter(parameters, "--icon", icon, true);
addParameter(parameters, "--license-file", licenseFile, true);
addParameter(parameters, "--app-image", appImage, true);
if (modulePaths != null) {
for (File modulePath : modulePaths) {
addParameter(parameters, "--module-path", modulePath, true);
}
}
if (addModules != null && !addModules.isEmpty()) {
addParameter(parameters, "--add-modules", String.join(",", addModules));
}
if (javaOptions != null) {
for (String option : javaOptions) {
addParameter(parameters, "--java-options", escape(option));
}
}
if (arguments != null) {
for (String arg : arguments) {
addParameter(parameters, "--arguments", escape(arg));
}
}
if (fileAssociations != null) {
for (File association : fileAssociations) {
addParameter(parameters, "--file-associations", association, true);
}
}
if (launchers != null) {
for (Launcher launcher : launchers) {
launcher.validate();
addParameter(parameters, "--add-launcher",
launcher.getName() + "=" + launcher.getFile().getAbsolutePath());
}
}
if (additionalOptions != null) {
for (String option : additionalOptions) {
addParameter(parameters, option);
}
}
if (isMac()) {
addParameter(parameters, "--mac-package-identifier", macPackageIdentifier);
addParameter(parameters, "--mac-package-name", macPackageName);
addParameter(parameters, "--mac-package-signing-prefix", macPackageSigningPrefix);
addParameter(parameters, "--mac-sign", macSign);
addParameter(parameters, "--mac-signing-keychain", macSigningKeychain, true);
addParameter(parameters, "--mac-signing-key-user-name", macSigningKeyUserName);
} else if (isWindows()) {
addParameter(parameters, "--win-menu", winMenu);
addParameter(parameters, "--win-dir-chooser", winDirChooser);
addParameter(parameters, "--win-upgrade-uuid", winUpgradeUuid);
addParameter(parameters, "--win-menu-group", winMenuGroup);
addParameter(parameters, "--win-shortcut", winShortcut);
addParameter(parameters, "--win-per-user-install", winPerUserInstall);
addParameter(parameters, "--win-console", winConsole);
} else if (isLinux()) {
addParameter(parameters, "--linux-package-name", linuxPackageName);
addParameter(parameters, "--linux-deb-maintainer", linuxDebMaintainer);
addParameter(parameters, "--linux-menu-group", linuxMenuGroup);
addParameter(parameters, "--linux-rpm-license-type", linuxRpmLicenseType);
addParameter(parameters, "--linux-app-release", linuxAppRelease);
addParameter(parameters, "--linux-app-category", linuxAppCategory);
addParameter(parameters, "--linux-shortcut", linuxShortcut);
}
}
private void addMandatoryParameter(List params,
@SuppressWarnings("SameParameterValue") String name,
String value) throws MojoFailureException
{
if (value == null || value.isEmpty()) {
throw new MojoFailureException("Mandatory parameter \"" + name + "\" cannot be null or empty");
}
addParameter(params, name, value);
}
private void addMandatoryParameter(List params,
@SuppressWarnings("SameParameterValue") String name,
File value) throws MojoFailureException
{
if (value == null) {
throw new MojoFailureException("Mandatory parameter \"" + name + "\" cannot be null or empty");
}
addParameter(params, name, value);
}
private void addParameter(List params, String name, String value) {
if (value == null || value.isEmpty()) {
return;
}
getLog().info(" " + name + " " + value);
params.add(name);
params.add(value);
}
private void addParameter(List params, String name, File value) throws MojoFailureException {
addParameter(params, name, value, false);
}
private void addParameter(List params, String name, File value, boolean checkExistence) throws MojoFailureException {
if (value == null) {
return;
}
if (checkExistence && !value.exists()) {
throw new MojoFailureException("File or directory " + value.getAbsolutePath() + " does not exist");
}
addParameter(params, name, value.getAbsolutePath());
}
private void addParameter(List params, String name) {
if (name == null || name.isEmpty()) {
return;
}
getLog().info(" " + name);
params.add(name);
}
private void addParameter(List params, String name, boolean value) {
if (!value) {
return;
}
getLog().info(" " + name);
params.add(name);
}
private void addParameter(List params, EnumParameter value) {
if (value == null) {
return;
}
addParameter(params, value.getParameterName(), value.getValue());
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy