
net.dongliu.jpackage.JPackageMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jpackage-maven-plugin Show documentation
Show all versions of jpackage-maven-plugin Show documentation
Easy ways to create JPackage Images
The newest version!
package net.dongliu.jpackage;
import net.dongliu.jpackage.model.JPackageLauncher;
import net.dongliu.jpackage.model.LinuxPackageSetting;
import net.dongliu.jpackage.model.MacPackageSetting;
import net.dongliu.jpackage.model.WindowsPackageSetting;
import net.dongliu.jpackage.util.ModuleInfo;
import net.dongliu.jpackage.util.ProcessResult;
import net.dongliu.jpackage.util.ProcessUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.*;
import org.apache.maven.project.MavenProject;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
import org.codehaus.plexus.util.Os;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* JPackage mojo, require jdk 14+, Only support modular apps
*
* @author dongliu
*/
@Mojo(name = "package", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution =
ResolutionScope.COMPILE_PLUS_RUNTIME)
public class JPackageMojo extends AbstractMojo {
@Parameter(defaultValue = "${project}", readonly = true)
private MavenProject project;
@Parameter(defaultValue = "${project.build.directory}/${project.build.finalName}.${project.packaging}")
private File projectArtifact;
@Component
private ToolchainManager toolchainManager;
@Parameter(defaultValue = "${session}", readonly = true)
private MavenSession mavenSession;
/**
* Name of the application and/or package
*/
@Parameter(defaultValue = "${project.name}")
private String name;
@Parameter(required = true)
private String type;
@Parameter(defaultValue = "${project.version}")
private String appVersion;
@Parameter(defaultValue = "${project.description}")
private String description;
@Parameter
private String copyright;
@Parameter
private String licenseFile;
@Parameter(defaultValue = "${project.build.directory}")
private String destination;
@Parameter(defaultValue = "${project.groupId}")
private String vendor;
@Parameter
private boolean verbose;
@Parameter
private boolean bindServices;
@Parameter
private List addModules;
@Parameter
private List modulePaths;
@Parameter
private String runtimeImage;
/**
* Jlink options. default is --strip-native-commands --strip-debug --no-man-pages --no-header-files
*/
@Parameter
private List jlinkOptions;
@Parameter
private String icon;
@Parameter
private String resourceDir;
@Parameter
private List launchers;
@Parameter
private List fileAssociations;
@Parameter
private List arguments;
@Parameter
private List javaOptions;
/**
* If is modular application, default false.
*/
@Parameter(defaultValue = "false")
private boolean modular;
/**
* The main module name, used for modular application. If not set, use default project artifact's module
*/
@Parameter
private String module;
/**
* The main jar, used for non-modular application. If not set, use default project artifact
*/
@Parameter
private String mainJar;
/**
* The input dir, for non-modular application
*/
@Parameter(defaultValue = "${project.build.directory}/jars")
private String inputDir;
/**
* main class name. If empty, will try to get class name from main module / main jar
*/
@Parameter
private String mainClass;
// mac parameters
@Parameter(name = "mac")
private MacPackageSetting macPackageSetting;
// linux parameters
@Parameter(name = "linux")
private LinuxPackageSetting linuxPackageSetting;
@Parameter(name = "win")
private WindowsPackageSetting windowsPackageSetting;
@Parameter(defaultValue = "${project.build.directory}/jars")
private File jarsDirectory;
@Override
public void execute() throws MojoExecutionException {
String packaging = project.getModel().getPackaging();
if (!packaging.equalsIgnoreCase("jar")) {
getLog().error("require packaging type to be jar or jmod, '" + packaging + " not supported'");
return;
}
if (modular) {
DescribeModule describeModule = new DescribeModule(getTools("jar"), getTools("jmod"), projectArtifact.toPath());
if (module == null || mainClass == null) {
ModuleInfo projectModuleInfo = describeModule.describe();
if (projectModuleInfo != null && projectModuleInfo.mainClass() != null) {
module = projectModuleInfo.name();
mainClass = projectModuleInfo.mainClass();
getLog().info("using main module: " + module + "/" + mainClass);
}
}
if (module == null) {
throw new RuntimeException("main module required");
}
} else {
if (mainJar == null) {
mainJar = projectArtifact.toPath().toString();
}
}
getLog().info("creating jpackage image at " + destination + File.separator + name);
runJPackage();
}
private Path getTools(String toolName) {
Toolchain toolchain = toolchainManager.getToolchainFromBuildContext("jdk", mavenSession);
Path toolPath;
if (toolchain != null) {
String toolPathStr = toolchain.findTool(toolName);
if (toolPathStr != null) {
toolPath = Paths.get(toolPathStr);
} else {
throw new RuntimeException("tools not found in tool chain: " + toolchain);
}
} else {
String javaHome = System.getProperty("java.home");
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
toolName = toolName + ".exe";
}
toolPath = Paths.get(javaHome, "bin", toolName);
}
return toolPath;
}
private void runJPackage() throws AssertionError {
List command = new ArrayList<>();
command.add(getTools("jpackage").toString());
command.add("--name");
command.add(name);
command.add("--type");
command.add(type);
command.add("--app-version");
command.add(appVersion);
command.add("--dest");
command.add(destination);
command.add("--vendor");
command.add(vendor);
if (description != null) {
command.add("--description");
command.add(description);
}
if (copyright != null) {
command.add("--copyright");
command.add(copyright);
}
if (licenseFile != null) {
command.add("-license-file");
command.add(licenseFile);
}
if (icon != null) {
command.add("--icon");
command.add(icon);
}
if (resourceDir == null) {
Path defaultResourceDir;
if (Os.isFamily(Os.FAMILY_MAC)) {
defaultResourceDir = project.getBasedir().toPath().resolve("src/main/deploy/osx");
} else if (Os.isFamily(Os.FAMILY_UNIX)) {
defaultResourceDir = project.getBasedir().toPath().resolve("src/main/deploy/linux");
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
defaultResourceDir = project.getBasedir().toPath().resolve("src/main/deploy/osx");
} else {
defaultResourceDir = null;
}
if (defaultResourceDir != null && Files.exists(defaultResourceDir)) {
resourceDir = defaultResourceDir.toString();
}
}
if (resourceDir != null) {
getLog().info("using resource dir: " + resourceDir);
command.add("--resource-dir");
command.add(resourceDir);
}
if (verbose) {
command.add("--verbose");
}
if (jlinkOptions != null && !jlinkOptions.isEmpty()) {
command.add("--jlink-options");
command.add(String.join(" ", jlinkOptions));
}
if (modular) {
command.add("--module");
command.add(module + "/" + mainClass);
} else {
command.add("--main-jar");
command.add(mainJar);
if (mainClass != null) {
command.add("--main-class");
command.add(mainClass);
}
}
if (bindServices) {
command.add("--bind-services");
}
if (addModules != null && !addModules.isEmpty()) {
command.add("--add-modules");
command.add(String.join(",", addModules));
}
if (modular) {
if (modulePaths != null && !modulePaths.isEmpty()) {
command.add("--module-path");
command.add(String.join(":", modulePaths));
}
} else {
command.add("--input");
command.add(inputDir);
}
if (runtimeImage != null) {
command.add("--runtime-image");
command.add(runtimeImage);
}
if (arguments != null && !arguments.isEmpty()) {
for (String argument : arguments) {
command.add("--arguments");
command.add(argument);
}
}
if (javaOptions != null && !javaOptions.isEmpty()) {
for (String javaOption : javaOptions) {
command.add("--java-options");
command.add(javaOption);
}
}
if (fileAssociations != null && !fileAssociations.isEmpty()) {
for (File fileAssociation : fileAssociations) {
command.add("--file-associations");
command.add(fileAssociation.toString());
}
}
if (launchers != null && !launchers.isEmpty()) {
for (JPackageLauncher launcher : launchers) {
command.add("--add-launcher");
command.add(String.format("%s=%s", launcher.getName(), launcher.getFile()));
}
}
if (Os.isFamily(Os.FAMILY_MAC) && macPackageSetting != null) {
addMacParameters(command);
}
if (Os.isFamily(Os.FAMILY_UNIX) && linuxPackageSetting != null) {
addLinuxParameters(command);
}
if (Os.isFamily(Os.FAMILY_WINDOWS) && windowsPackageSetting != null) {
addWindowsParameters(command);
}
copyArtifacts();
getLog().info("run jpackage: " + String.join(" ", command));
ProcessResult result = ProcessUtils.execute(command.toArray(String[]::new));
if (result.exitCode() != 0) {
String message = result.stderr().isEmpty() ? result.stdout() : result.stderr();
getLog().error("jpackage error: " + message);
}
}
private void addWindowsParameters(List command) {
if (windowsPackageSetting.isConsole()) {
command.add("--win-console");
}
if (windowsPackageSetting.isDirChooser()) {
command.add("--win-dir-chooser");
}
if (windowsPackageSetting.isMenu()) {
command.add("--win-menu");
}
if (windowsPackageSetting.getMenuGroup() != null) {
command.add("--win-menu-group");
command.add(windowsPackageSetting.getMenuGroup());
}
if (windowsPackageSetting.isPerUserInstall()) {
command.add("--win-per-user-install");
}
if (windowsPackageSetting.isShortcut()) {
command.add("--win-shortcut");
}
if (windowsPackageSetting.getUpgradeUuid() != null) {
command.add("--win-upgrade-uuid");
command.add(windowsPackageSetting.getUpgradeUuid());
}
if (windowsPackageSetting.getInstallDir() != null) {
command.add("--install-dir");
command.add(windowsPackageSetting.getInstallDir());
}
}
private void addLinuxParameters(List command) {
if (linuxPackageSetting.getPackageName() != null) {
command.add("--linux-package-name");
command.add(linuxPackageSetting.getPackageName());
}
if (linuxPackageSetting.getDebMaintainer() != null) {
command.add("--linux-deb-maintainer");
command.add(linuxPackageSetting.getDebMaintainer());
}
if (linuxPackageSetting.getMenuGroup() != null) {
command.add("--linux-menu-group");
command.add(linuxPackageSetting.getMenuGroup());
}
if (linuxPackageSetting.getPackageDeps() != null) {
command.add("--linux-package-deps");
command.add(linuxPackageSetting.getPackageDeps());
}
if (linuxPackageSetting.getRpmLicenseType() != null) {
command.add("--linux-rpm-license-type");
command.add(linuxPackageSetting.getRpmLicenseType());
}
if (linuxPackageSetting.getAppRelease() != null) {
command.add("--linux-app-release");
command.add(linuxPackageSetting.getAppRelease());
}
if (linuxPackageSetting.getAppCategory() != null) {
command.add("--linux-app-category");
command.add(linuxPackageSetting.getAppCategory());
}
if (linuxPackageSetting.isShortcut()) {
command.add("--linux-shortcut");
}
if (linuxPackageSetting.getInstallDir() != null) {
command.add("--install-dir");
command.add(linuxPackageSetting.getInstallDir());
}
}
private void addMacParameters(List command) {
if (macPackageSetting.getPackageIdentifier() != null) {
command.add("--mac-package-identifier");
command.add(macPackageSetting.getPackageIdentifier());
}
if (macPackageSetting.getPackageName() != null) {
command.add("--mac-package-name");
command.add(macPackageSetting.getPackageName());
}
if (macPackageSetting.getPackageSigningPrefix() != null) {
command.add("--mac-package-signing-prefix");
command.add(macPackageSetting.getPackageSigningPrefix());
}
if (macPackageSetting.isSign()) {
command.add("--mac-sign");
}
if (macPackageSetting.getSigningKeychain() != null) {
command.add("--mac-signing-keychain");
command.add(macPackageSetting.getSigningKeychain());
}
if (macPackageSetting.getSigningKeyUserName() != null) {
command.add("--mac-signing-key-user-name");
command.add(macPackageSetting.getSigningKeyUserName());
}
if (macPackageSetting.getInstallDir() != null) {
command.add("--install-dir");
command.add(macPackageSetting.getInstallDir());
}
}
private void copyArtifacts() {
Path outputPath = jarsDirectory.toPath();
if (!jarsDirectory.exists()) {
jarsDirectory.mkdir();
}
Set dependencies = project.getArtifacts();
for (Artifact artifact : dependencies) {
String scope = artifact.getScope();
if (!scope.equals("compile") && !scope.equals("runtime")) {
continue;
}
Path inputFile = artifact.getFile().toPath();
Path outputJar = jarsDirectory.toPath().resolve(inputFile.getFileName());
try {
Files.copy(inputFile, outputJar, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new UncheckedIOException("Couldn't copy JAR file", e);
}
}
Path projectJarPath = projectArtifact.toPath();
Path outputJar = jarsDirectory.toPath().resolve(projectJarPath.getFileName());
try {
Files.copy(projectJarPath, outputJar, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new UncheckedIOException("Couldn't copy JAR file", e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy