8241716: Jpackage functionality to let users choose whether to create shortcuts

Reviewed-by: almatvee, herrick
This commit is contained in:
Alexey Semenyuk 2021-03-11 16:55:23 +00:00
parent 3820ab9e82
commit 7ed46bd02e
22 changed files with 1265 additions and 191 deletions

View File

@ -330,6 +330,11 @@ public class Arguments {
setOptionValue("win-shortcut", true);
}),
WIN_SHORTCUT_PROMPT ("win-shortcut-prompt",
OptionCategories.PLATFORM_WIN, () -> {
setOptionValue("win-shortcut-prompt", true);
}),
WIN_PER_USER_INSTALLATION ("win-per-user-install",
OptionCategories.PLATFORM_WIN, () -> {
setOptionValue("win-per-user-install", false);

View File

@ -96,6 +96,7 @@ class ValidOptions {
options.put(CLIOptions.WIN_MENU_HINT.getId(), USE.INSTALL);
options.put(CLIOptions.WIN_MENU_GROUP.getId(), USE.INSTALL);
options.put(CLIOptions.WIN_SHORTCUT_HINT.getId(), USE.INSTALL);
options.put(CLIOptions.WIN_SHORTCUT_PROMPT.getId(), USE.INSTALL);
options.put(CLIOptions.WIN_DIR_CHOOSER.getId(), USE.INSTALL);
options.put(CLIOptions.WIN_UPGRADE_UUID.getId(), USE.INSTALL);
options.put(CLIOptions.WIN_PER_USER_INSTALLATION.getId(),

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -205,13 +205,16 @@ MSG_Help_win_install=\
\ Adds a dialog to enable the user to choose a directory in which\n\
\ the product is installed\n\
\ --win-menu\n\
\ Adds the application to the system menu\n\
\ Request to add a Start menu shortcut for this application\n\
\ --win-menu-group <menu group name>\n\
\ Start Menu group this application is placed in\n\
\ --win-per-user-install\n\
\ Request to perform an install on a per-user basis\n\
\ --win-shortcut\n\
\ Creates a desktop shortcut for the application\n\
\ Request to add desktop shortcut for this application\n\
\ --win-shortcut-prompt\n\
\ Adds a dialog to enable the user to choose if shortcuts\n\
\ will be created by installer\n\
\ --win-upgrade-uuid <id string>\n\
\ UUID associated with upgrades for this package\n\

View File

@ -31,7 +31,24 @@ MSG_Help=\u4F7F\u7528\u65B9\u6CD5: jpackage <options>\n\n\u4F7F\u7528\u4F8B:\n--
\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u8907\u6570\u56DE\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n --install-dir <file path>\n {4} --license-file <file path>\n \u30E9\u30A4\u30BB\u30F3\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n --resource-dir <path>\n \u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9jpackage\u30EA\u30BD\u30FC\u30B9\u3078\u306E\u30D1\u30B9\n \u30A2\u30A4\u30B3\u30F3\u3001\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u304A\u3088\u3073jpackage\u306E\u305D\u306E\u4ED6\u306E\u30EA\u30BD\u30FC\u30B9\u306F\u3001\n \u3053\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u7F6E\u63DB\u30EA\u30BD\u30FC\u30B9\u3092\u8FFD\u52A0\u3059\u308B\u3053\u3068\u3067\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3067\u304D\u307E\u3059\u3002\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n --runtime-image <file-path>\n \u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3059\u308B\u4E8B\u524D\u5B9A\u7FA9\u6E08\u307F\u306E\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30A4\u30E1\u30FC\u30B8\u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\n \u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u4F5C\u6210\u6642\u306B\u306F\u3001\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u5FC5\u8981\u3067\u3059\u3002\n\n\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u4F5C\u6210\u3059\u308B\u305F\u3081\u306E\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u4F9D\u5B58\u30AA\u30D7\u30B7\u30E7\u30F3:\n{3}
MSG_Help_win_launcher=\n\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30E9\u30F3\u30C1\u30E3\u3092\u4F5C\u6210\u3059\u308B\u305F\u3081\u306E\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u4F9D\u5B58\u30AA\u30D7\u30B7\u30E7\u30F3:\n --win-console\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30B3\u30F3\u30BD\u30FC\u30EB\u30FB\u30E9\u30F3\u30C1\u30E3\u3092\u4F5C\u6210\u3057\u307E\u3059\u3002\u30B3\u30F3\u30BD\u30FC\u30EB\u30FB\n \u30A4\u30F3\u30BF\u30E9\u30AF\u30B7\u30E7\u30F3\u304C\u5FC5\u8981\u306A\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306B\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\n
MSG_Help_win_install=\ --win-dir-chooser\n \u30E6\u30FC\u30B6\u30FC\u304C\u88FD\u54C1\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3059\u308B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u9078\u629E\n \u3059\u308B\u305F\u3081\u306E\u30C0\u30A4\u30A2\u30ED\u30B0\u3092\u8FFD\u52A0\u3057\u307E\u3059\n --win-menu\n \u30B7\u30B9\u30C6\u30E0\u30FB\u30E1\u30CB\u30E5\u30FC\u306B\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u8FFD\u52A0\u3057\u307E\u3059\n --win-menu-group <menu group name>\n \u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u914D\u7F6E\u3059\u308B\u30B9\u30BF\u30FC\u30C8\u30FB\u30E1\u30CB\u30E5\u30FC\u30FB\u30B0\u30EB\u30FC\u30D7\n --win-per-user-install\n \u30E6\u30FC\u30B6\u30FC\u3054\u3068\u306B\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3092\u5B9F\u884C\u3059\u308B\u3088\u3046\u306B\u30EA\u30AF\u30A8\u30B9\u30C8\u3057\u307E\u3059\n --win-shortcut\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30C7\u30B9\u30AF\u30C8\u30C3\u30D7\u30FB\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u4F5C\u6210\u3057\u307E\u3059\n --win-upgrade-uuid <id string>\n \u3053\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30A2\u30C3\u30D7\u30B0\u30EC\u30FC\u30C9\u306B\u95A2\u9023\u4ED8\u3051\u3089\u308C\u3066\u3044\u308BUUID\n
MSG_Help_win_install=\
\ --win-dir-chooser\n\
\ Adds a dialog to enable the user to choose a directory in which\n\
\ the product is installed\n\
\ --win-menu\n\
\ Request to add a Start menu shortcut for this application\n\
\ --win-menu-group <menu group name>\n\
\ Start Menu group this application is placed in\n\
\ --win-per-user-install\n\
\ Request to perform an install on a per-user basis\n\
\ --win-shortcut\n\
\ Request to add desktop shortcut for this application\n\
\ --win-shortcut-prompt\n\
\ Adds a dialog to enable the user to choose if shortcuts\n\
\ will be created by installer\n\
\ --win-upgrade-uuid <id string>\n\
\ UUID associated with upgrades for this package\n\
MSG_Help_win_install_dir=\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u5834\u6240\u306E\u4E0B\u306E\u76F8\u5BFE\u30B5\u30D6\u30D1\u30B9\n
MSG_Help_mac_launcher=\ --mac-package-identifier <ID string>\n MacOS\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u4E00\u610F\u306B\u8B58\u5225\u3059\u308BID\n \u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u540D\u306B\u30C7\u30D5\u30A9\u30EB\u30C8\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059\u3002\n \u82F1\u6570\u5B57(A-Z\u3001a-z\u30010-9)\u3001\u30CF\u30A4\u30D5\u30F3(-)\n \u304A\u3088\u3073\u30D4\u30EA\u30AA\u30C9(.)\u6587\u5B57\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002\n --mac-package-name <name string>\n \u30E1\u30CB\u30E5\u30FC\u30FB\u30D0\u30FC\u306B\u8868\u793A\u3055\u308C\u308B\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u540D\u524D\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D\u3068\u306F\u7570\u306A\u308A\u307E\u3059\u3002\n \u3053\u306E\u540D\u524D\u306F16\u6587\u5B57\u672A\u6E80\u306B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u3001\u30E1\u30CB\u30E5\u30FC\u30FB\u30D0\u30FC\n \u304A\u3088\u3073\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u60C5\u5831\u30A6\u30A3\u30F3\u30C9\u30A6\u306B\u8868\u793A\u3059\u308B\u306E\u306B\u9069\u3057\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D\u306B\u30C7\u30D5\u30A9\u30EB\u30C8\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059\u3002\n --mac-package-signing-prefix <prefix string>\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u306B\u7F72\u540D\u3059\u308B\u969B\u3001\u65E2\u5B58\u306E\u30D1\u30C3\u30B1\u30FC\u30B8ID\u306E\u306A\u3044\n \u7F72\u540D\u304C\u5FC5\u8981\u306A\u3059\u3079\u3066\u306E\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u306B\u3001\n \u3053\u306E\u5024\u304C\u63A5\u982D\u8F9E\u3068\u3057\u3066\u4ED8\u3051\u3089\u308C\u307E\u3059\u3002\n --mac-sign\n \u30D1\u30C3\u30B1\u30FC\u30B8\u306B\u7F72\u540D\u3059\u308B\u3088\u3046\u30EA\u30AF\u30A8\u30B9\u30C8\u3057\u307E\u3059\n --mac-signing-keychain <file path>\n \u7F72\u540D\u30A2\u30A4\u30C7\u30F3\u30C6\u30A3\u30C6\u30A3\u3092\u691C\u7D22\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\n (\u7D76\u5BFE\u30D1\u30B9\u307E\u305F\u306F\u73FE\u5728\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9)\u3002\n \u6307\u5B9A\u3057\u306A\u304B\u3063\u305F\u5834\u5408\u3001\u6A19\u6E96\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u304C\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002\n --mac-signing-key-user-name <team name>\n Apple\u7F72\u540D\u30A2\u30A4\u30C7\u30F3\u30C6\u30A3\u30C6\u30A3\u306E\u540D\u524D\u306E\u30C1\u30FC\u30E0\u540D\u90E8\u5206\u3002\n \u4F8B: "Developer ID Application: "\n
MSG_Help_linux_install=\ --linux-package-name <package name>\n Linux\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u540D\u524D\u3002\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D\u306B\u30C7\u30D5\u30A9\u30EB\u30C8\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059\n --linux-deb-maintainer <email address>\n .deb\u30D1\u30C3\u30B1\u30FC\u30B8\u306EMaintainer\n --linux-menu-group <menu-group-name>\n \u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u304C\u914D\u7F6E\u3055\u308C\u3066\u3044\u308B\u30E1\u30CB\u30E5\u30FC\u30FB\u30B0\u30EB\u30FC\u30D7\n --linux-package-deps\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306B\u5FC5\u8981\u306A\u30D1\u30C3\u30B1\u30FC\u30B8\u307E\u305F\u306F\u6A5F\u80FD\n --linux-rpm-license-type <type string>\n \u30E9\u30A4\u30BB\u30F3\u30B9\u306E\u30BF\u30A4\u30D7(RPM .spec\u306E"License: <value>")\n --linux-app-release <release value>\n RPM <name>.spec\u30D5\u30A1\u30A4\u30EB\u306E\u30EA\u30EA\u30FC\u30B9\u5024\u307E\u305F\u306F \n DEB\u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\u30FB\u30D5\u30A1\u30A4\u30EB\u306EDebian\u30EA\u30D3\u30B8\u30E7\u30F3\u5024\u3002\n --linux-app-category <category value>\n RPM <name>.spec\u30D5\u30A1\u30A4\u30EB\u306E\u30B0\u30EB\u30FC\u30D7\u5024\u307E\u305F\u306F \n DEB\u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u5024\u3002\n --linux-shortcut\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u4F5C\u6210\u3057\u307E\u3059\n

View File

@ -30,7 +30,24 @@ MSG_Help=\u7528\u6CD5\uFF1Ajpackage <options>\n\n\u793A\u4F8B\u7528\u6CD5:\n----
\uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\n \u5728\u521B\u5EFA\u8FD0\u884C\u65F6\u7A0B\u5E8F\u5305\u65F6\u9700\u8981\u4F7F\u7528\u9009\u9879\u3002\n\n\u7528\u6765\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u5305\u7684\u4E0E\u5E73\u53F0\u76F8\u5173\u7684\u9009\u9879\uFF1A\n{3}
MSG_Help_win_launcher=\n\u7528\u6765\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u542F\u52A8\u7A0B\u5E8F\u7684\u4E0E\u5E73\u53F0\u76F8\u5173\u7684\u9009\u9879\uFF1A\n --win-console\n \u4E3A\u5E94\u7528\u7A0B\u5E8F\u521B\u5EFA\u63A7\u5236\u53F0\u542F\u52A8\u7A0B\u5E8F\uFF0C\u5E94\u5F53\u4E3A\n \u9700\u8981\u63A7\u5236\u53F0\u4EA4\u4E92\u7684\u5E94\u7528\u7A0B\u5E8F\u6307\u5B9A\n
MSG_Help_win_install=\ --win-dir-chooser\n \u6DFB\u52A0\u4E00\u4E2A\u5BF9\u8BDD\u6846\u4EE5\u5141\u8BB8\u7528\u6237\u9009\u62E9\n \u4EA7\u54C1\u7684\u5B89\u88C5\u76EE\u5F55\n --win-menu\n \u5C06\u8BE5\u5E94\u7528\u7A0B\u5E8F\u6DFB\u52A0\u5230\u7CFB\u7EDF\u83DC\u5355\u4E2D\n --win-menu-group <menu group name>\n \u542F\u52A8\u8BE5\u5E94\u7528\u7A0B\u5E8F\u6240\u5728\u7684\u83DC\u5355\u7EC4\n --win-per-user-install\n \u8BF7\u6C42\u57FA\u4E8E\u6BCF\u4E2A\u7528\u6237\u6267\u884C\u5B89\u88C5\n --win-shortcut\n \u4E3A\u5E94\u7528\u7A0B\u5E8F\u521B\u5EFA\u684C\u9762\u5FEB\u6377\u65B9\u5F0F\n --win-upgrade-uuid <id string>\n \u4E0E\u6B64\u7A0B\u5E8F\u5305\u5347\u7EA7\u76F8\u5173\u8054\u7684 UUID\n
MSG_Help_win_install=\
\ --win-dir-chooser\n\
\ Adds a dialog to enable the user to choose a directory in which\n\
\ the product is installed\n\
\ --win-menu\n\
\ Request to add a Start menu shortcut for this application\n\
\ --win-menu-group <menu group name>\n\
\ Start Menu group this application is placed in\n\
\ --win-per-user-install\n\
\ Request to perform an install on a per-user basis\n\
\ --win-shortcut\n\
\ Request to add desktop shortcut for this application\n\
\ --win-shortcut-prompt\n\
\ Adds a dialog to enable the user to choose if shortcuts\n\
\ will be created by installer\n\
\ --win-upgrade-uuid <id string>\n\
\ UUID associated with upgrades for this package\n\
MSG_Help_win_install_dir=\u9ED8\u8BA4\u5B89\u88C5\u4F4D\u7F6E\u4E0B\u9762\u7684\u76F8\u5BF9\u5B50\u8DEF\u5F84\n
MSG_Help_mac_launcher=\ --mac-package-identifier <ID string>\n \u7528\u6765\u552F\u4E00\u5730\u6807\u8BC6 macOS \u5E94\u7528\u7A0B\u5E8F\u7684\u6807\u8BC6\u7B26\n \u9ED8\u8BA4\u4E3A\u4E3B\u7C7B\u540D\u79F0\u3002\n \u53EA\u80FD\u4F7F\u7528\u5B57\u6BCD\u6570\u5B57\uFF08A-Z\u3001a-z\u30010-9\uFF09\u3001\u8FDE\u5B57\u7B26 (-) \u548C\n \u53E5\u70B9 (.) \u5B57\u7B26\u3002\n --mac-package-name <name string>\n \u51FA\u73B0\u5728\u83DC\u5355\u680F\u4E2D\u7684\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0\n \u8FD9\u53EF\u4EE5\u4E0E\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0\u4E0D\u540C\u3002\n \u6B64\u540D\u79F0\u7684\u957F\u5EA6\u5FC5\u987B\u5C0F\u4E8E 16 \u4E2A\u5B57\u7B26\uFF0C\u9002\u5408\n \u663E\u793A\u5728\u83DC\u5355\u680F\u4E2D\u548C\u5E94\u7528\u7A0B\u5E8F\u201C\u4FE1\u606F\u201D\u7A97\u53E3\u4E2D\u3002\n \u9ED8\u8BA4\u4E3A\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0\u3002\n --mac-package-signing-prefix <prefix string>\n \u5728\u5BF9\u5E94\u7528\u7A0B\u5E8F\u5305\u7B7E\u540D\u65F6\uFF0C\u4F1A\u5728\u6240\u6709\u9700\u8981\u7B7E\u540D\n \u4F46\u5F53\u524D\u6CA1\u6709\u7A0B\u5E8F\u5305\u6807\u8BC6\u7B26\u7684\u7EC4\u4EF6\u7684\n \u524D\u9762\u52A0\u4E0A\u6B64\u503C\u3002\n --mac-sign\n \u8BF7\u6C42\u5BF9\u7A0B\u5E8F\u5305\u8FDB\u884C\u7B7E\u540D\n --mac-signing-keychain <file path>\n \u8981\u7528\u6765\u641C\u7D22\u7B7E\u540D\u8EAB\u4EFD\u7684\u5BC6\u94A5\u94FE\u7684\u8DEF\u5F84\n \uFF08\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u4E8E\u5F53\u524D\u76EE\u5F55\u7684\u8DEF\u5F84\uFF09\u3002\n \u5982\u679C\u672A\u6307\u5B9A\uFF0C\u5219\u4F7F\u7528\u6807\u51C6\u7684\u5BC6\u94A5\u94FE\u3002\n --mac-signing-key-user-name <team name>\n Apple \u7B7E\u540D\u8EAB\u4EFD\u540D\u79F0\u4E2D\u7684\u56E2\u961F\u540D\u79F0\u9009\u9879\u3002\n \u4F8B\u5982\uFF0C"Developer ID Application: "\n
MSG_Help_linux_install=\ --linux-package-name <package name>\n Linux \u7A0B\u5E8F\u5305\u7684\u540D\u79F0\uFF0C\u9ED8\u8BA4\u4E3A\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0\n --linux-deb-maintainer <email address>\n .deb \u7A0B\u5E8F\u5305\u7684\u7EF4\u62A4\u7A0B\u5E8F\n --linux-menu-group <menu-group-name>\n \u6B64\u5E94\u7528\u7A0B\u5E8F\u6240\u5728\u7684\u83DC\u5355\u7EC4\n --linux-package-deps\n \u5E94\u7528\u7A0B\u5E8F\u6240\u9700\u7684\u7A0B\u5E8F\u5305\u6216\u529F\u80FD\n --linux-rpm-license-type <type string>\n \u8BB8\u53EF\u8BC1\u7684\u7C7B\u578B\uFF08RPM .spec \u7684 "License: <value>"\uFF09\n --linux-app-release <release value>\n RPM <name>.spec \u6587\u4EF6\u7684\u53D1\u884C\u7248\u503C\u6216\n DEB \u63A7\u5236\u6587\u4EF6\u7684 Debian \u4FEE\u8BA2\u7248\u503C\u3002\n --linux-app-category <category value>\n RPM <name>.spec \u6587\u4EF6\u7684\u7EC4\u503C\u6216\n DEB \u63A7\u5236\u6587\u4EF6\u7684\u533A\u57DF\u503C\u3002\n --linux-shortcut\n \u4E3A\u5E94\u7528\u7A0B\u5E8F\u521B\u5EFA\u5FEB\u6377\u65B9\u5F0F\n

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -82,7 +82,9 @@ import org.xml.sax.SAXException;
* <li>main.wxs. Main source file with the installer description
* <li>bundle.wxf. Source file with application and Java run-time directory tree
* description.
* <li>ui.wxf. Source file with UI description of the installer.
* </ul>
*
* <p>
* main.wxs file is a copy of main.wxs resource from
* jdk.jpackage.internal.resources package. It is parametrized with the
@ -104,15 +106,20 @@ import org.xml.sax.SAXException;
* variable is set to the value of --win-upgrade-uuid command line option
* <li>JpAllowDowngrades. Set to "yes" if --win-upgrade-uuid command line option
* was specified. Undefined otherwise
* <li>JpLicenseRtf. Set to the value of --license-file command line option.
* Undefined is --license-file command line option was not specified
* <li>JpInstallDirChooser. Set to "yes" if --win-dir-chooser command line
* option was specified. Undefined otherwise
* <li>JpConfigDir. Absolute path to the directory with generated WiX source
* files.
* <li>JpIsSystemWide. Set to "yes" if --win-per-user-install command line
* option was not specified. Undefined otherwise
* </ul>
*
* <p>
* ui.wxf file is generated based on --license-file, --win-shortcut-prompt,
* --win-dir-chooser command line options. It is parametrized with the following
* WiX variables:
* <ul>
* <li>JpLicenseRtf. Set to the value of --license-file command line option.
* Undefined if --license-file command line option was not specified
* </ul>
*/
public class WinMsiBundler extends AbstractBundler {
@ -151,7 +158,6 @@ public class WinMsiBundler extends AbstractBundler {
: Boolean.valueOf(s)
);
public static final StandardBundlerParam<String> PRODUCT_VERSION =
new StandardBundlerParam<>(
"win.msi.productVersion",
@ -184,16 +190,15 @@ public class WinMsiBundler extends AbstractBundler {
},
(s, p) -> s);
private static final BundlerParamInfo<Boolean> INSTALLDIR_CHOOSER =
new StandardBundlerParam<> (
Arguments.CLIOptions.WIN_DIR_CHOOSER.getId(),
Boolean.class,
params -> Boolean.FALSE,
(s, p) -> Boolean.valueOf(s)
);
public WinMsiBundler() {
appImageBundler = new WinAppBundler().setDependentTask(true);
wixFragments = Stream.of(
Map.entry("bundle.wxf", new WixAppImageFragmentBuilder()),
Map.entry("ui.wxf", new WixUiFragmentBuilder())
).map(e -> {
e.getValue().setOutputFileName(e.getKey());
return e.getValue();
}).collect(Collectors.toList());
}
@Override
@ -277,9 +282,10 @@ public class WinMsiBundler extends AbstractBundler {
toolInfo.version));
}
wixSourcesBuilder.setWixVersion(wixToolset.get(WixTool.Light).version);
wixFragments.forEach(wixFragment -> wixFragment.setWixVersion(
wixToolset.get(WixTool.Light).version));
wixSourcesBuilder.logWixFeatures();
wixFragments.get(0).logWixFeatures();
/********* validate bundle parameters *************/
@ -369,10 +375,10 @@ public class WinMsiBundler extends AbstractBundler {
prepareProto(params);
wixSourcesBuilder
.initFromParams(WIN_APP_IMAGE.fetchFrom(params), params)
.createMainFragment(CONFIG_ROOT.fetchFrom(params).resolve(
"bundle.wxf"));
for (var wixFragment : wixFragments) {
wixFragment.initFromParams(params);
wixFragment.addFilesToConfigRoot();
}
Map<String, String> wixVars = prepareMainProjectFile(params);
@ -424,22 +430,6 @@ public class WinMsiBundler extends AbstractBundler {
data.put("JpIsSystemWide", "yes");
}
String licenseFile = LICENSE_FILE.fetchFrom(params);
if (licenseFile != null) {
String lname = IOUtils.getFileName(Path.of(licenseFile)).toString();
Path destFile = CONFIG_ROOT.fetchFrom(params).resolve(lname);
data.put("JpLicenseRtf", destFile.toAbsolutePath().toString());
}
// Copy CA dll to include with installer
if (INSTALLDIR_CHOOSER.fetchFrom(params)) {
data.put("JpInstallDirChooser", "yes");
String fname = "wixhelper.dll";
try (InputStream is = OverridableResource.readDefault(fname)) {
Files.copy(is, CONFIG_ROOT.fetchFrom(params).resolve(fname));
}
}
// Copy standard l10n files.
for (String loc : Arrays.asList("en", "ja", "zh_CN")) {
String fname = "MsiInstallerStrings_" + loc + ".wxl";
@ -476,23 +466,20 @@ public class WinMsiBundler extends AbstractBundler {
entry -> entry.getValue().path)))
.setWixObjDir(TEMP_ROOT.fetchFrom(params).resolve("wixobj"))
.setWorkDir(WIN_APP_IMAGE.fetchFrom(params))
.addSource(CONFIG_ROOT.fetchFrom(params).resolve("main.wxs"), wixVars)
.addSource(CONFIG_ROOT.fetchFrom(params).resolve("bundle.wxf"), null);
.addSource(CONFIG_ROOT.fetchFrom(params).resolve("main.wxs"), wixVars);
for (var wixFragment : wixFragments) {
wixFragment.configureWixPipeline(wixPipeline);
}
Log.verbose(MessageFormat.format(I18N.getString(
"message.generating-msi"), msiOut.toAbsolutePath().toString()));
boolean enableLicenseUI = (LICENSE_FILE.fetchFrom(params) != null);
boolean enableInstalldirUI = INSTALLDIR_CHOOSER.fetchFrom(params);
wixPipeline.addLightOptions("-sice:ICE27");
if (!MSI_SYSTEM_WIDE.fetchFrom(params)) {
wixPipeline.addLightOptions("-sice:ICE91");
}
if (enableLicenseUI || enableInstalldirUI) {
wixPipeline.addLightOptions("-ext", "WixUIExtension");
}
final Path primaryWxlFile = CONFIG_ROOT.fetchFrom(params).resolve(
I18N.getString("resource.wxl-file-name")).toAbsolutePath();
@ -512,12 +499,6 @@ public class WinMsiBundler extends AbstractBundler {
wixPipeline.addLightOptions(uniqueCultures.stream().collect(
Collectors.joining(";", "-cultures:", "")));
// Only needed if we using CA dll, so Wix can find it
if (enableInstalldirUI) {
wixPipeline.addLightOptions("-b", CONFIG_ROOT.fetchFrom(params)
.toAbsolutePath().toString());
}
wixPipeline.buildMsi(msiOut.toAbsolutePath());
return msiOut;
@ -643,6 +624,6 @@ public class WinMsiBundler extends AbstractBundler {
private Path installerIcon;
private Map<WixTool, WixTool.ToolInfo> wixToolset;
private AppImageBundler appImageBundler;
private WixSourcesBuilder wixSourcesBuilder = new WixSourcesBuilder();
private List<WixFragmentBuilder> wixFragments;
}

View File

@ -31,6 +31,7 @@ import java.nio.file.Path;
import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@ -54,19 +55,19 @@ import static jdk.jpackage.internal.StandardBundlerParam.INSTALL_DIR;
import static jdk.jpackage.internal.StandardBundlerParam.VENDOR;
import static jdk.jpackage.internal.StandardBundlerParam.VERSION;
import static jdk.jpackage.internal.WinMsiBundler.MSI_SYSTEM_WIDE;
import static jdk.jpackage.internal.WinMsiBundler.WIN_APP_IMAGE;
/**
* Creates application WiX source files.
* Creates WiX fragment with components for contents of app image.
*/
class WixSourcesBuilder {
class WixAppImageFragmentBuilder extends WixFragmentBuilder {
WixSourcesBuilder setWixVersion(DottedVersion v) {
wixVersion = v;
return this;
}
@Override
void initFromParams(Map<String, ? super Object> params) {
super.initFromParams(params);
Path appImageRoot = WIN_APP_IMAGE.fetchFrom(params);
WixSourcesBuilder initFromParams(Path appImageRoot,
Map<String, ? super Object> params) {
Supplier<ApplicationLayout> appImageSupplier = () -> {
if (StandardBundlerParam.isRuntimeInstaller(params)) {
return ApplicationLayout.javaRuntime();
@ -101,64 +102,50 @@ class WixSourcesBuilder {
installedAppImage = appImageSupplier.get().resolveAt(INSTALLDIR);
shortcutFolders = new HashSet<>();
if (SHORTCUT_HINT.fetchFrom(params)) {
shortcutFolders.add(ShortcutsFolder.Desktop);
}
if (MENU_HINT.fetchFrom(params)) {
shortcutFolders.add(ShortcutsFolder.ProgramMenu);
}
shortcutFolders = Stream.of(ShortcutsFolder.values()).filter(
shortcutFolder -> shortcutFolder.requested(params)).collect(
Collectors.toSet());
if (StandardBundlerParam.isRuntimeInstaller(params)) {
launcherPaths = Collections.emptyList();
} else {
launcherPaths = AppImageFile.getLauncherNames(appImageRoot, params).stream()
.map(name -> installedAppImage.launchersDirectory().resolve(name))
.map(WixSourcesBuilder::addExeSuffixToPath)
.map(WixAppImageFragmentBuilder::addExeSuffixToPath)
.collect(Collectors.toList());
}
programMenuFolderName = MENU_GROUP.fetchFrom(params);
initFileAssociations(params);
return this;
}
void createMainFragment(Path file) throws IOException {
@Override
void addFilesToConfigRoot() throws IOException {
removeFolderItems = new HashMap<>();
defaultedMimes = new HashSet<>();
IOUtils.createXml(file, xml -> {
xml.writeStartElement("Wix");
xml.writeDefaultNamespace("http://schemas.microsoft.com/wix/2006/wi");
xml.writeNamespace("util",
"http://schemas.microsoft.com/wix/UtilExtension");
xml.writeStartElement("Fragment");
addFaComponentGroup(xml);
addShortcutComponentGroup(xml);
addFilesComponentGroup(xml);
xml.writeEndElement(); // <Fragment>
addIconsFragment(xml);
xml.writeEndElement(); // <Wix>
});
super.addFilesToConfigRoot();
}
void logWixFeatures() {
if (wixVersion.compareTo("3.6") >= 0) {
Log.verbose(MessageFormat.format(I18N.getString(
"message.use-wix36-features"), wixVersion));
}
}
@Override
protected Collection<XmlConsumer> getFragmentWriters() {
return List.of(
xml -> {
addFaComponentGroup(xml);
static boolean is64Bit() {
return !("x86".equals(System.getProperty("os.arch")));
addShortcutComponentGroup(xml);
addFilesComponentGroup(xml);
for (var shortcutFolder : shortcutFolders) {
xml.writeStartElement("Property");
xml.writeAttribute("Id", shortcutFolder.property);
xml.writeAttribute("Value", "1");
xml.writeEndElement();
}
},
this::addIcons
);
}
private void normalizeFileAssociation(FileAssociation fa) {
@ -365,6 +352,17 @@ class WixSourcesBuilder {
Component.startElement(xml, componentId, String.format("{%s}",
role.guidOf(path)));
if (role == Component.Shortcut) {
xml.writeStartElement("Condition");
String property = shortcutFolders.stream().filter(shortcutFolder -> {
return path.startsWith(shortcutFolder.root);
}).map(shortcutFolder -> {
return shortcutFolder.property;
}).findFirst().get();
xml.writeCharacters(property);
xml.writeEndElement();
}
boolean isRegistryKeyPath = !systemWide || role.isRegistryKeyPath();
if (isRegistryKeyPath) {
addRegistryKeyPath(xml, directoryRefPath);
@ -659,7 +657,7 @@ class WixSourcesBuilder {
addComponentGroup(xml, "Files", componentIds);
}
private void addIconsFragment(XMLStreamWriter xml) throws
private void addIcons(XMLStreamWriter xml) throws
XMLStreamException, IOException {
PathGroup srcPathGroup = appImage.pathGroup();
@ -680,14 +678,12 @@ class WixSourcesBuilder {
}
});
xml.writeStartElement("Fragment");
for (var icoFile : icoFiles) {
xml.writeStartElement("Icon");
xml.writeAttribute("Id", Id.Icon.of(icoFile.getValue()));
xml.writeAttribute("SourceFile", icoFile.getKey().toString());
xml.writeEndElement();
}
xml.writeEndElement();
}
private void addRegistryKeyPath(XMLStreamWriter xml, Path path) throws
@ -705,7 +701,7 @@ class WixSourcesBuilder {
xml.writeStartElement("RegistryKey");
xml.writeAttribute("Root", regRoot);
xml.writeAttribute("Key", registryKeyPath);
if (wixVersion.compareTo("3.6") < 0) {
if (getWixVersion().compareTo("3.6") < 0) {
xml.writeAttribute("Action", "createAndRemoveOnUninstall");
}
xml.writeStartElement("RegistryValue");
@ -719,7 +715,7 @@ class WixSourcesBuilder {
private String addDirectoryCleaner(XMLStreamWriter xml, Path path) throws
XMLStreamException, IOException {
if (wixVersion.compareTo("3.6") < 0) {
if (getWixVersion().compareTo("3.6") < 0) {
return null;
}
@ -775,24 +771,46 @@ class WixSourcesBuilder {
}
enum ShortcutsFolder {
ProgramMenu(PROGRAM_MENU_PATH),
Desktop(DESKTOP_PATH);
ProgramMenu(PROGRAM_MENU_PATH, Arguments.CLIOptions.WIN_MENU_HINT,
"JP_INSTALL_STARTMENU_SHORTCUT", "JpStartMenuShortcutPrompt"),
Desktop(DESKTOP_PATH, Arguments.CLIOptions.WIN_SHORTCUT_HINT,
"JP_INSTALL_DESKTOP_SHORTCUT", "JpDesktopShortcutPrompt");
private ShortcutsFolder(Path root) {
private ShortcutsFolder(Path root, Arguments.CLIOptions cliOption,
String property, String wixVariableName) {
this.root = root;
this.bundlerParam = new StandardBundlerParam<>(
cliOption.getId(),
Boolean.class,
params -> false,
// valueOf(null) is false,
// and we actually do want null in some cases
(s, p) -> (s == null || "null".equalsIgnoreCase(s)) ? false : Boolean.valueOf(s)
);
this.wixVariableName = wixVariableName;
this.property = property;
}
Path getPath(WixSourcesBuilder outer) {
Path getPath(WixAppImageFragmentBuilder outer) {
if (this == ProgramMenu) {
return root.resolve(outer.programMenuFolderName);
}
return root;
}
private final Path root;
}
boolean requested(Map<String, ? super Object> params) {
return bundlerParam.fetchFrom(params);
}
private DottedVersion wixVersion;
String getWixVariableName() {
return wixVariableName;
}
private final Path root;
private final String property;
private final String wixVariableName;
private final StandardBundlerParam<Boolean> bundlerParam;
}
private boolean systemWide;
@ -839,28 +857,6 @@ class WixSourcesBuilder {
private final static Set<Path> USER_PROFILE_DIRS = Set.of(LOCAL_PROGRAM_FILES,
PROGRAM_MENU_PATH, DESKTOP_PATH);
private static final StandardBundlerParam<Boolean> MENU_HINT =
new StandardBundlerParam<>(
Arguments.CLIOptions.WIN_MENU_HINT.getId(),
Boolean.class,
params -> false,
// valueOf(null) is false,
// and we actually do want null in some cases
(s, p) -> (s == null ||
"null".equalsIgnoreCase(s))? true : Boolean.valueOf(s)
);
private static final StandardBundlerParam<Boolean> SHORTCUT_HINT =
new StandardBundlerParam<>(
Arguments.CLIOptions.WIN_SHORTCUT_HINT.getId(),
Boolean.class,
params -> false,
// valueOf(null) is false,
// and we actually do want null in some cases
(s, p) -> (s == null ||
"null".equalsIgnoreCase(s))? false : Boolean.valueOf(s)
);
private static final StandardBundlerParam<String> MENU_GROUP =
new StandardBundlerParam<>(
Arguments.CLIOptions.WIN_MENU_GROUP.getId(),

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jpackage.internal;
import java.io.IOException;
import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import jdk.jpackage.internal.IOUtils.XmlConsumer;
import jdk.jpackage.internal.OverridableResource.Source;
import static jdk.jpackage.internal.OverridableResource.createResource;
import static jdk.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
/**
* Creates WiX fragment.
*/
abstract class WixFragmentBuilder {
void setWixVersion(DottedVersion v) {
wixVersion = v;
}
void setOutputFileName(String v) {
outputFileName = v;
}
void initFromParams(Map<String, ? super Object> params) {
wixVariables = null;
additionalResources = null;
configRoot = CONFIG_ROOT.fetchFrom(params);
fragmentResource = createResource(outputFileName, params).setSourceOrder(
Source.ResourceDir);
}
void logWixFeatures() {
if (wixVersion.compareTo("3.6") >= 0) {
Log.verbose(MessageFormat.format(I18N.getString(
"message.use-wix36-features"), wixVersion));
}
}
void configureWixPipeline(WixPipeline wixPipeline) {
wixPipeline.addSource(configRoot.resolve(outputFileName),
Optional.ofNullable(wixVariables).map(WixVariables::getValues).orElse(
null));
}
void addFilesToConfigRoot() throws IOException {
Path fragmentPath = configRoot.resolve(outputFileName);
if (fragmentResource.saveToFile(fragmentPath) == null) {
createWixSource(fragmentPath, xml -> {
for (var fragmentWriter : getFragmentWriters()) {
xml.writeStartElement("Fragment");
fragmentWriter.accept(xml);
xml.writeEndElement(); // <Fragment>
}
});
}
if (additionalResources != null) {
for (var resource : additionalResources) {
resource.resource.saveToFile(configRoot.resolve(
resource.saveAsName));
}
}
}
DottedVersion getWixVersion() {
return wixVersion;
}
static boolean is64Bit() {
return !("x86".equals(System.getProperty("os.arch")));
}
protected Path getConfigRoot() {
return configRoot;
}
protected abstract Collection<XmlConsumer> getFragmentWriters();
protected void defineWixVariable(String variableName) {
setWixVariable(variableName, "yes");
}
protected void setWixVariable(String variableName, String variableValue) {
if (wixVariables == null) {
wixVariables = new WixVariables();
}
wixVariables.setWixVariable(variableName, variableValue);
}
protected void addResource(OverridableResource resource, String saveAsName) {
if (additionalResources == null) {
additionalResources = new ArrayList<>();
}
additionalResources.add(new ResourceWithName(resource, saveAsName));
}
static void createWixSource(Path file, XmlConsumer xmlConsumer)
throws IOException {
IOUtils.createXml(file, xml -> {
xml.writeStartElement("Wix");
xml.writeDefaultNamespace("http://schemas.microsoft.com/wix/2006/wi");
xml.writeNamespace("util",
"http://schemas.microsoft.com/wix/UtilExtension");
xmlConsumer.accept(xml);
xml.writeEndElement(); // <Wix>
});
}
private static class ResourceWithName {
ResourceWithName(OverridableResource resource, String saveAsName) {
this.resource = resource;
this.saveAsName = saveAsName;
}
private final OverridableResource resource;
private final String saveAsName;
}
private DottedVersion wixVersion;
private WixVariables wixVariables;
private List<ResourceWithName> additionalResources;
private OverridableResource fragmentResource;
private String outputFileName;
private Path configRoot;
}

View File

@ -112,7 +112,7 @@ public class WixPipeline {
"-nologo",
adjustPath.apply(wixSource.source).toString(),
"-ext", "WixUtilExtension",
"-arch", WixSourcesBuilder.is64Bit() ? "x64" : "x86",
"-arch", WixFragmentBuilder.is64Bit() ? "x64" : "x86",
"-out", wixObj.toAbsolutePath().toString()
));

View File

@ -0,0 +1,501 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jpackage.internal;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import jdk.jpackage.internal.IOUtils.XmlConsumer;
import static jdk.jpackage.internal.OverridableResource.createResource;
import static jdk.jpackage.internal.StandardBundlerParam.LICENSE_FILE;
import jdk.jpackage.internal.WixAppImageFragmentBuilder.ShortcutsFolder;
/**
* Creates UI WiX fragment.
*/
final class WixUiFragmentBuilder extends WixFragmentBuilder {
@Override
void initFromParams(Map<String, ? super Object> params) {
super.initFromParams(params);
String licenseFile = LICENSE_FILE.fetchFrom(params);
withLicenseDlg = licenseFile != null;
if (withLicenseDlg) {
Path licenseFileName = IOUtils.getFileName(Path.of(licenseFile));
Path destFile = getConfigRoot().resolve(licenseFileName);
setWixVariable("JpLicenseRtf", destFile.toAbsolutePath().toString());
}
withInstallDirChooserDlg = INSTALLDIR_CHOOSER.fetchFrom(params);
List<ShortcutsFolder> shortcutFolders = Stream.of(
ShortcutsFolder.values()).filter(shortcutFolder -> {
return shortcutFolder.requested(params)
&& SHORTCUT_PROMPT.fetchFrom(params);
}).collect(Collectors.toList());
withShortcutPromptDlg = !shortcutFolders.isEmpty();
customDialogs = new ArrayList<>();
if (withShortcutPromptDlg) {
CustomDialog dialog = new CustomDialog(params, I18N.getString(
"resource.shortcutpromptdlg-wix-file"),
"ShortcutPromptDlg.wxs");
for (var shortcutFolder : shortcutFolders) {
dialog.wixVariables.defineWixVariable(
shortcutFolder.getWixVariableName());
}
customDialogs.add(dialog);
}
if (withInstallDirChooserDlg) {
CustomDialog dialog = new CustomDialog(params, I18N.getString(
"resource.installdirnotemptydlg-wix-file"),
"InstallDirNotEmptyDlg.wxs");
List<Dialog> dialogIds = getUI().dialogIdsSupplier.apply(this);
dialog.wixVariables.setWixVariable("JpAfterInstallDirDlg",
dialogIds.get(dialogIds.indexOf(Dialog.InstallDirDlg) + 1).id);
customDialogs.add(dialog);
}
}
@Override
void configureWixPipeline(WixPipeline wixPipeline) {
super.configureWixPipeline(wixPipeline);
if (withShortcutPromptDlg || withInstallDirChooserDlg || withLicenseDlg) {
wixPipeline.addLightOptions("-ext", "WixUIExtension");
}
// Only needed if we using CA dll, so Wix can find it
if (withInstallDirChooserDlg) {
wixPipeline.addLightOptions("-b",
getConfigRoot().toAbsolutePath().toString());
}
for (var customDialog : customDialogs) {
customDialog.addToWixPipeline(wixPipeline);
}
}
@Override
void addFilesToConfigRoot() throws IOException {
super.addFilesToConfigRoot();
if (withInstallDirChooserDlg) {
String fname = "wixhelper.dll"; // CA dll
try (InputStream is = OverridableResource.readDefault(fname)) {
Files.copy(is, getConfigRoot().resolve(fname));
}
}
}
@Override
protected Collection<XmlConsumer> getFragmentWriters() {
return List.of(this::addUI);
}
private void addUI(XMLStreamWriter xml) throws XMLStreamException,
IOException {
if (withInstallDirChooserDlg) {
xml.writeStartElement("Property");
xml.writeAttribute("Id", "WIXUI_INSTALLDIR");
xml.writeAttribute("Value", "INSTALLDIR");
xml.writeEndElement(); // Property
}
if (withLicenseDlg) {
xml.writeStartElement("WixVariable");
xml.writeAttribute("Id", "WixUILicenseRtf");
xml.writeAttribute("Value", "$(var.JpLicenseRtf)");
xml.writeEndElement(); // WixVariable
}
xml.writeStartElement("UI");
xml.writeAttribute("Id", "JpUI");
var ui = getUI();
if (ui != null) {
ui.write(this, xml);
}
xml.writeEndElement(); // UI
}
private UI getUI() {
if (withInstallDirChooserDlg || withShortcutPromptDlg) {
// WixUI_InstallDir for shortcut prompt dialog too because in
// WixUI_Minimal UI sequence WelcomeEulaDlg dialog doesn't have "Next"
// button, but has "Install" button. So inserting shortcut prompt dialog
// after welcome dialog in WixUI_Minimal UI sequence would be confusing
return UI.InstallDir;
} else if (withLicenseDlg) {
return UI.Minimal;
} else {
return null;
}
}
private enum UI {
InstallDir("WixUI_InstallDir",
WixUiFragmentBuilder::dialogSequenceForWixUI_InstallDir,
Dialog::createPairsForWixUI_InstallDir),
Minimal("WixUI_Minimal", null, null);
UI(String wixUIRef,
Function<WixUiFragmentBuilder, List<Dialog>> dialogIdsSupplier,
Supplier<Map<DialogPair, List<Publish>>> dialogPairsSupplier) {
this.wixUIRef = wixUIRef;
this.dialogIdsSupplier = dialogIdsSupplier;
this.dialogPairsSupplier = dialogPairsSupplier;
}
void write(WixUiFragmentBuilder outer, XMLStreamWriter xml) throws
XMLStreamException, IOException {
xml.writeStartElement("UIRef");
xml.writeAttribute("Id", wixUIRef);
xml.writeEndElement(); // UIRef
if (dialogIdsSupplier != null) {
List<Dialog> dialogIds = dialogIdsSupplier.apply(outer);
Map<DialogPair, List<Publish>> dialogPairs = dialogPairsSupplier.get();
if (dialogIds.contains(Dialog.InstallDirDlg)) {
xml.writeStartElement("DialogRef");
xml.writeAttribute("Id", "InstallDirNotEmptyDlg");
xml.writeEndElement(); // DialogRef
}
var it = dialogIds.iterator();
Dialog firstId = it.next();
while (it.hasNext()) {
Dialog secondId = it.next();
DialogPair pair = new DialogPair(firstId, secondId);
for (var curPair : List.of(pair, pair.flip())) {
for (var publish : dialogPairs.get(curPair)) {
writePublishDialogPair(xml, publish, curPair);
}
}
firstId = secondId;
}
}
}
private final String wixUIRef;
private final Function<WixUiFragmentBuilder, List<Dialog>> dialogIdsSupplier;
private final Supplier<Map<DialogPair, List<Publish>>> dialogPairsSupplier;
}
private List<Dialog> dialogSequenceForWixUI_InstallDir() {
List<Dialog> dialogIds = new ArrayList<>(
List.of(Dialog.WixUI_WelcomeDlg));
if (withLicenseDlg) {
dialogIds.add(Dialog.WixUI_LicenseAgreementDlg);
}
if (withInstallDirChooserDlg) {
dialogIds.add(Dialog.InstallDirDlg);
}
if (withShortcutPromptDlg) {
dialogIds.add(Dialog.ShortcutPromptDlg);
}
dialogIds.add(Dialog.WixUI_VerifyReadyDlg);
return dialogIds;
}
private enum Dialog {
WixUI_WelcomeDlg,
WixUI_LicenseAgreementDlg,
InstallDirDlg,
ShortcutPromptDlg,
WixUI_VerifyReadyDlg;
Dialog() {
if (name().startsWith("WixUI_")) {
id = name().substring("WixUI_".length());
} else {
id = name();
}
}
static Map<DialogPair, List<Publish>> createPair(Dialog firstId,
Dialog secondId, List<PublishBuilder> nextBuilders,
List<PublishBuilder> prevBuilders) {
var pair = new DialogPair(firstId, secondId);
return Map.of(pair, nextBuilders.stream().map(b -> {
return buildPublish(b.create()).next().create();
}).collect(Collectors.toList()), pair.flip(),
prevBuilders.stream().map(b -> {
return buildPublish(b.create()).back().create();
}).collect(Collectors.toList()));
}
static Map<DialogPair, List<Publish>> createPair(Dialog firstId,
Dialog secondId, List<PublishBuilder> builders) {
return createPair(firstId, secondId, builders, builders);
}
static Map<DialogPair, List<Publish>> createPairsForWixUI_InstallDir() {
Map<DialogPair, List<Publish>> map = new HashMap<>();
// Order is a "weight" of action. If there are multiple
// "NewDialog" action for the same dialog Id, MSI would pick the one
// with higher order value. In WixUI_InstallDir dialog sequence the
// highest order value is 4. InstallDirNotEmptyDlg adds NewDialog
// action with order 5. Setting order to 6 for all
// actions configured in this function would make them executed
// instead of corresponding default actions defined in
// WixUI_InstallDir dialog sequence.
var order = 6;
// Based on WixUI_InstallDir.wxs
var backFromVerifyReadyDlg = List.of(buildPublish().condition(
"NOT Installed").order(order));
var uncondinal = List.of(buildPublish().condition("1"));
var ifNotIstalled = List.of(
buildPublish().condition("NOT Installed").order(order));
var ifLicenseAccepted = List.of(buildPublish().condition(
"LicenseAccepted = \"1\"").order(order));
// Empty condition list for the default dialog sequence
map.putAll(createPair(WixUI_WelcomeDlg, WixUI_LicenseAgreementDlg,
List.of()));
map.putAll(
createPair(WixUI_WelcomeDlg, InstallDirDlg, ifNotIstalled));
map.putAll(createPair(WixUI_WelcomeDlg, ShortcutPromptDlg,
ifNotIstalled));
map.putAll(createPair(WixUI_LicenseAgreementDlg, InstallDirDlg,
List.of()));
map.putAll(createPair(WixUI_LicenseAgreementDlg, ShortcutPromptDlg,
ifLicenseAccepted, uncondinal));
map.putAll(createPair(WixUI_LicenseAgreementDlg,
WixUI_VerifyReadyDlg, ifLicenseAccepted,
backFromVerifyReadyDlg));
map.putAll(createPair(InstallDirDlg, ShortcutPromptDlg, List.of(),
uncondinal));
map.putAll(createPair(InstallDirDlg, WixUI_VerifyReadyDlg, List.of()));
map.putAll(createPair(ShortcutPromptDlg, WixUI_VerifyReadyDlg,
uncondinal, backFromVerifyReadyDlg));
return map;
}
private final String id;
}
private final static class DialogPair {
DialogPair(Dialog first, Dialog second) {
this(first.id, second.id);
}
DialogPair(String firstId, String secondId) {
this.firstId = firstId;
this.secondId = secondId;
}
DialogPair flip() {
return new DialogPair(secondId, firstId);
}
@Override
public int hashCode() {
int hash = 3;
hash = 97 * hash + Objects.hashCode(this.firstId);
hash = 97 * hash + Objects.hashCode(this.secondId);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DialogPair other = (DialogPair) obj;
if (!Objects.equals(this.firstId, other.firstId)) {
return false;
}
if (!Objects.equals(this.secondId, other.secondId)) {
return false;
}
return true;
}
private final String firstId;
private final String secondId;
}
private final static class Publish {
Publish(String control, String condition, int order) {
this.control = control;
this.condition = condition;
this.order = order;
}
private final String control;
private final String condition;
private final int order;
}
private final static class PublishBuilder {
PublishBuilder() {
order(0);
next();
condition("1");
}
PublishBuilder(Publish publish) {
order(publish.order);
control(publish.control);
condition(publish.condition);
}
public PublishBuilder control(String v) {
control = v;
return this;
}
public PublishBuilder next() {
return control("Next");
}
public PublishBuilder back() {
return control("Back");
}
public PublishBuilder condition(String v) {
condition = v;
return this;
}
public PublishBuilder order(int v) {
order = v;
return this;
}
Publish create() {
return new Publish(control, condition, order);
}
private String control;
private String condition;
private int order;
}
private static PublishBuilder buildPublish() {
return new PublishBuilder();
}
private static PublishBuilder buildPublish(Publish publish) {
return new PublishBuilder(publish);
}
private static void writePublishDialogPair(XMLStreamWriter xml,
Publish publish, DialogPair dialogPair) throws IOException,
XMLStreamException {
xml.writeStartElement("Publish");
xml.writeAttribute("Dialog", dialogPair.firstId);
xml.writeAttribute("Control", publish.control);
xml.writeAttribute("Event", "NewDialog");
xml.writeAttribute("Value", dialogPair.secondId);
if (publish.order != 0) {
xml.writeAttribute("Order", String.valueOf(publish.order));
}
xml.writeCharacters(publish.condition);
xml.writeEndElement();
}
private final class CustomDialog {
CustomDialog(Map<String, ? super Object> params, String category,
String wxsFileName) {
this.wxsFileName = wxsFileName;
this.wixVariables = new WixVariables();
addResource(
createResource(wxsFileName, params).setCategory(category),
wxsFileName);
}
void addToWixPipeline(WixPipeline wixPipeline) {
wixPipeline.addSource(getConfigRoot().toAbsolutePath().resolve(
wxsFileName), wixVariables.getValues());
}
private final WixVariables wixVariables;
private final String wxsFileName;
}
private boolean withInstallDirChooserDlg;
private boolean withShortcutPromptDlg;
private boolean withLicenseDlg;
private List<CustomDialog> customDialogs;
private static final BundlerParamInfo<Boolean> INSTALLDIR_CHOOSER
= new StandardBundlerParam<>(
Arguments.CLIOptions.WIN_DIR_CHOOSER.getId(),
Boolean.class,
params -> false,
(s, p) -> Boolean.valueOf(s)
);
private static final StandardBundlerParam<Boolean> SHORTCUT_PROMPT
= new StandardBundlerParam<>(
Arguments.CLIOptions.WIN_SHORTCUT_PROMPT.getId(),
Boolean.class,
params -> false,
(s, p) -> Boolean.valueOf(s)
);
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jpackage.internal;
import java.util.HashMap;
import java.util.Map;
final class WixVariables {
void defineWixVariable(String variableName) {
setWixVariable(variableName, "yes");
}
void setWixVariable(String variableName, String variableValue) {
values.put(variableName, variableValue);
}
Map<String, String> getValues() {
return values;
}
private final Map<String, String> values = new HashMap<>();
}

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Fragment>
<Binary Id="JpCaDll" SourceFile="wixhelper.dll"/>
<CustomAction Id="JpCheckInstallDir" BinaryKey="JpCaDll" DllEntry="CheckInstallDir" />
<UI>
<Dialog Id="InstallDirNotEmptyDlg" Width="300" Height="85" Title="!(loc.InstallDirNotEmptyDlg_Title)">
<Control Id="Yes" Type="PushButton" X="100" Y="55" Width="50" Height="15" Default="no" Cancel="no" Text="!(loc.WixUIYes)">
<Publish Event="NewDialog" Value="$(var.JpAfterInstallDirDlg)">1</Publish>
</Control>
<Control Id="No" Type="PushButton" X="150" Y="55" Width="50" Height="15" Default="yes" Cancel="yes" Text="!(loc.WixUINo)">
<Publish Event="NewDialog" Value="InstallDirDlg">1</Publish>
</Control>
<Control Id="Text" Type="Text" X="25" Y="15" Width="250" Height="30" TabSkip="no">
<Text>!(loc.message.install.dir.exist)</Text>
</Control>
</Dialog>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="JpCheckInstallDir" Order="3">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="InstallDirNotEmptyDlg" Order="5">INSTALLDIR_VALID="0"</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="$(var.JpAfterInstallDirDlg)" Order="5">INSTALLDIR_VALID="1"</Publish>
</UI>
</Fragment>
</Wix>

View File

@ -4,4 +4,12 @@
<String Id="MainFeatureTitle">Main Feature</String>
<String Id="DowngradeErrorMessage">A higher version of [ProductName] is already installed. Downgrades disabled. Setup will now exit.</String>
<String Id="DisallowUpgradeErrorMessage">A lower version of [ProductName] is already installed. Upgrades disabled. Setup will now exit.</String>
<String Id="ShortcutPromptDlg_Title">[ProductName] Setup</String>
<String Id="ShortcutPromptDlgTitle">{\WixUI_Font_Title}Shortcuts</String>
<String Id="ShortcutPromptDlgBannerBitmap">WixUI_Bmp_Banner</String>
<String Id="ShortcutPromptDlgDescription">Select shortcuts to create.</String>
<String Id="ShortcutPromptDlgDesktopShortcutControlLabel">Create desktop shortcut(s)</String>
<String Id="ShortcutPromptDlgStartMenuShortcutControlLabel">Create start menu shortcut(s)</String>
<String Id="InstallDirNotEmptyDlg_Title">[ProductName] Setup</String>
</WixLocalization>

View File

@ -4,4 +4,12 @@
<String Id="MainFeatureTitle">主な機能</String>
<String Id="DowngradeErrorMessage">[ProductName]のより上位のバージョンがすでにインストールされています。ダウングレードは無効です。セットアップを終了します。</String>
<String Id="DisallowUpgradeErrorMessage">[ProductName]のより下位のバージョンがすでにインストールされています。アップグレードは無効です。セットアップを終了します。</String>
<String Id="ShortcutPromptDlg_Title">[ProductName] Setup</String>
<String Id="ShortcutPromptDlgTitle">{\WixUI_Font_Title}Shortcuts</String>
<String Id="ShortcutPromptDlgBannerBitmap">WixUI_Bmp_Banner</String>
<String Id="ShortcutPromptDlgDescription">Select shortcuts to create.</String>
<String Id="ShortcutPromptDlgDesktopShortcutControlLabel">Create desktop shortcut(s)</String>
<String Id="ShortcutPromptDlgStartMenuShortcutControlLabel">Create start menu shortcut(s)</String>
<String Id="InstallDirNotEmptyDlg_Title">[ProductName] Setup</String>
</WixLocalization>

View File

@ -4,4 +4,12 @@
<String Id="MainFeatureTitle">主要功能</String>
<String Id="DowngradeErrorMessage">已安装更高版本的 [ProductName]。降级已禁用。现在将退出安装。</String>
<String Id="DisallowUpgradeErrorMessage">已安装更低版本的 [ProductName]。升级已禁用。现在将退出安装。</String>
<String Id="ShortcutPromptDlg_Title">[ProductName] Setup</String>
<String Id="ShortcutPromptDlgTitle">{\WixUI_Font_Title}Shortcuts</String>
<String Id="ShortcutPromptDlgBannerBitmap">WixUI_Bmp_Banner</String>
<String Id="ShortcutPromptDlgDescription">Select shortcuts to create.</String>
<String Id="ShortcutPromptDlgDesktopShortcutControlLabel">Create desktop shortcut(s)</String>
<String Id="ShortcutPromptDlgStartMenuShortcutControlLabel">Create start menu shortcut(s)</String>
<String Id="InstallDirNotEmptyDlg_Title">[ProductName] Setup</String>
</WixLocalization>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<?define JpDesktopShortcutPromptControlY=140 ?>
<?define JpStartMenuShortcutPromptControlY=180 ?>
<?ifndef JpDesktopShortcutPrompt ?>
<?define JpStartMenuShortcutPromptControlY=$(var.JpDesktopShortcutPromptControlY) ?>
<?endif?>
<Fragment>
<UI>
<Dialog Id="ShortcutPromptDlg" Width="370" Height="270" Title="!(loc.ShortcutPromptDlg_Title)" NoMinimize="yes">
<Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"
Text="!(loc.ShortcutPromptDlgDescription)" />
<Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes"
Text="!(loc.ShortcutPromptDlgTitle)" />
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no"
Text="!(loc.ShortcutPromptDlgBannerBitmap)" />
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<?ifdef JpDesktopShortcutPrompt ?>
<Control Type="CheckBox" X="20" Width="200" Height="17" CheckBoxValue="1"
Id="InstallDesktopShortcut"
Y="$(var.JpDesktopShortcutPromptControlY)"
Property="JP_INSTALL_DESKTOP_SHORTCUT"
Text="!(loc.ShortcutPromptDlgDesktopShortcutControlLabel)"/>
<?endif?>
<?ifdef JpStartMenuShortcutPrompt ?>
<Control Type="CheckBox" X="20" Width="200" Height="17" CheckBoxValue="1"
Id="InstallStartMenuShortcut"
Y="$(var.JpStartMenuShortcutPromptControlY)"
Property="JP_INSTALL_STARTMENU_SHORTCUT"
Text="!(loc.ShortcutPromptDlgStartMenuShortcutControlLabel)"/>
<?endif?>
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes"
Text="!(loc.WixUINext)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17"
Text="!(loc.WixUIBack)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes"
Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
</Dialog>
</UI>
</Fragment>
</Wix>

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -37,6 +37,8 @@ resource.post-msi-script=script to run after msi file for exe installer is creat
resource.wxl-file-name=MsiInstallerStrings_en.wxl
resource.main-wix-file=Main WiX project file
resource.overrides-wix-file=Overrides WiX project file
resource.shortcutpromptdlg-wix-file=Shortcut prompt dialog WiX project file
resource.installdirnotemptydlg-wix-file=Not empty install directory dialog WiX project file
error.no-wix-tools=Can not find WiX tools (light.exe, candle.exe)
error.no-wix-tools.advice=Download WiX 3.0 or later from https://wixtoolset.org and add it to the PATH.

View File

@ -37,6 +37,8 @@ resource.post-msi-script=exe\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u306Emsi\u30D5\
resource.wxl-file-name=MsiInstallerStrings_ja.wxl
resource.main-wix-file=\u30E1\u30A4\u30F3WiX\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB
resource.overrides-wix-file=WiX\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9
resource.shortcutpromptdlg-wix-file=Shortcut prompt dialog WiX project file
resource.installdirnotemptydlg-wix-file=Not empty install directory dialog WiX project file
error.no-wix-tools=WiX\u30C4\u30FC\u30EB(light.exe\u3001candle.exe)\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
error.no-wix-tools.advice=WiX 3.0\u4EE5\u964D\u3092https://wixtoolset.org\u304B\u3089\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u3001PATH\u306B\u8FFD\u52A0\u3057\u307E\u3059\u3002

View File

@ -37,6 +37,8 @@ resource.post-msi-script=\u5728\u4E3A exe \u5B89\u88C5\u7A0B\u5E8F\u521B\u5EFA m
resource.wxl-file-name=MsiInstallerStrings_zh_CN.wxl
resource.main-wix-file=\u4E3B WiX \u9879\u76EE\u6587\u4EF6
resource.overrides-wix-file=\u8986\u76D6 WiX \u9879\u76EE\u6587\u4EF6
resource.shortcutpromptdlg-wix-file=Shortcut prompt dialog WiX project file
resource.installdirnotemptydlg-wix-file=Not empty install directory dialog WiX project file
error.no-wix-tools=\u627E\u4E0D\u5230 WiX \u5DE5\u5177 (light.exe, candle.exe)
error.no-wix-tools.advice=\u4ECE https://wixtoolset.org \u4E0B\u8F7D WiX 3.0 \u6216\u66F4\u9AD8\u7248\u672C\uFF0C\u7136\u540E\u5C06\u5176\u6DFB\u52A0\u5230 PATH\u3002

View File

@ -74,64 +74,14 @@
<ComponentGroupRef Id="FileAssociations"/>
</Feature>
<?ifdef JpInstallDirChooser ?>
<Binary Id="JpCaDll" SourceFile="wixhelper.dll"/>
<CustomAction Id="JpCheckInstallDir" BinaryKey="JpCaDll" DllEntry="CheckInstallDir" />
<?endif?>
<CustomAction Id="JpSetARPINSTALLLOCATION" Property="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
<?ifdef JpIcon ?>
<Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/>
<Icon Id="JpARPPRODUCTICON" SourceFile="$(var.JpIcon)"/>
<?endif?>
<UI>
<?ifdef JpInstallDirChooser ?>
<Dialog Id="JpInvalidInstallDir" Width="300" Height="85" Title="[ProductName] Setup" NoMinimize="yes">
<Control Id="JpInvalidInstallDirYes" Type="PushButton" X="100" Y="55" Width="50" Height="15" Default="no" Cancel="no" Text="Yes">
<Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
</Control>
<Control Id="JpInvalidInstallDirNo" Type="PushButton" X="150" Y="55" Width="50" Height="15" Default="yes" Cancel="yes" Text="No">
<Publish Event="NewDialog" Value="InstallDirDlg">1</Publish>
</Control>
<Control Id="Text" Type="Text" X="25" Y="15" Width="250" Height="30" TabSkip="no">
<Text>!(loc.message.install.dir.exist)</Text>
</Control>
</Dialog>
<!--
Run WixUI_InstallDir dialog in the default install directory.
-->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR"/>
<UIRef Id="WixUI_InstallDir" />
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="JpCheckInstallDir" Order="3">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="JpInvalidInstallDir" Order="5">INSTALLDIR_VALID="0"</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="5">INSTALLDIR_VALID="1"</Publish>
<?ifndef JpLicenseRtf ?>
<!--
No license file provided.
Override the dialog sequence in built-in dialog set "WixUI_InstallDir"
to exclude license dialog.
-->
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="2">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">1</Publish>
<?endif?>
<?else?>
<?ifdef JpLicenseRtf ?>
<UIRef Id="WixUI_Minimal" />
<?endif?>
<?endif?>
</UI>
<?ifdef JpLicenseRtf ?>
<WixVariable Id="WixUILicenseRtf" Value="$(var.JpLicenseRtf)"/>
<?endif?>
<UIRef Id="JpUI"/>
<InstallExecuteSequence>
<Custom Action="JpSetARPINSTALLLOCATION" After="CostFinalize">Not Installed</Custom>

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.nio.file.Path;
import java.util.ArrayList;
import jdk.jpackage.test.PackageTest;
import jdk.jpackage.test.JPackageCommand;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.test.Annotations.Parameters;
import java.util.List;
import jdk.jpackage.test.PackageType;
import jdk.jpackage.test.TKit;
/**
* Test all possible combinations of --win-dir-chooser, --win-shortcut-prompt
* and --license parameters.
*/
/*
* @test
* @summary jpackage with --win-dir-chooser, --win-shortcut-prompt and --license parameters
* @library ../helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
* @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinInstallerUiTest
*/
public class WinInstallerUiTest {
public WinInstallerUiTest(Boolean withDirChooser, Boolean withLicense,
Boolean withShortcutPrompt) {
this.withShortcutPrompt = withShortcutPrompt;
this.withDirChooser = withDirChooser;
this.withLicense = withLicense;
}
@Parameters
public static List<Object[]> data() {
List<Object[]> data = new ArrayList<>();
for (var withDirChooser : List.of(Boolean.TRUE, Boolean.FALSE)) {
for (var withLicense : List.of(Boolean.TRUE, Boolean.FALSE)) {
for (var withShortcutPrompt : List.of(Boolean.TRUE, Boolean.FALSE)) {
data.add(new Object[]{withDirChooser, withLicense,
withShortcutPrompt});
}
}
}
return data;
}
@Test
public void test() {
PackageTest test = new PackageTest()
.forTypes(PackageType.WINDOWS)
.configureHelloApp();
test.addInitializer(JPackageCommand::setFakeRuntime);
test.addInitializer(this::setPackageName);
if (withDirChooser) {
test.addInitializer(cmd -> cmd.addArgument("--win-dir-chooser"));
}
if (withShortcutPrompt) {
test.addInitializer(cmd -> {
cmd.addArgument("--win-shortcut-prompt");
cmd.addArgument("--win-menu");
cmd.addArgument("--win-shortcut");
});
}
if (withLicense) {
test.addInitializer(cmd -> {
cmd.addArguments("--license-file", TKit.createRelativePathCopy(
TKit.TEST_SRC_ROOT.resolve(Path.of("resources",
"license.txt"))));
});
}
test.run();
}
private void setPackageName(JPackageCommand cmd) {
StringBuilder sb = new StringBuilder(cmd.name());
sb.append("With");
if (withDirChooser) {
sb.append("DirChooser");
}
if (withShortcutPrompt) {
sb.append("ShortcutPrompt");
}
if (withLicense) {
sb.append("License");
}
cmd.setArgumentValue("--name", sb.toString());
}
private final boolean withDirChooser;
private final boolean withLicense;
private final boolean withShortcutPrompt;
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.ArrayList;
import jdk.jpackage.test.PackageTest;
import jdk.jpackage.test.JPackageCommand;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.test.Annotations.Parameters;
import java.util.List;
import jdk.jpackage.test.PackageType;
/**
* Test all possible combinations of --win-shortcut-prompt, --win-menu and
* --win-shortcut parameters.
*/
/*
* @test
* @summary jpackage with --win-shortcut-prompt, --win-menu and --win-shortcut parameters
* @library ../helpers
* @key jpackagePlatformPackage
* @build jdk.jpackage.test.*
* @requires (os.family == "windows")
* @modules jdk.jpackage/jdk.jpackage.internal
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=WinShortcutPromptTest
*/
public class WinShortcutPromptTest {
public WinShortcutPromptTest(Boolean withStartMenuShortcut,
Boolean withDesktopShortcut, Boolean withShortcutPrompt) {
this.withStartMenuShortcut = withStartMenuShortcut;
this.withDesktopShortcut = withDesktopShortcut;
this.withShortcutPrompt = withShortcutPrompt;
}
@Parameters
public static List<Object[]> data() {
List<Object[]> data = new ArrayList<>();
for (var withStartMenuShortcut : List.of(Boolean.TRUE, Boolean.FALSE)) {
for (var withDesktopShortcut : List.of(Boolean.TRUE, Boolean.FALSE)) {
for (var withShortcutPrompt : List.of(Boolean.TRUE, Boolean.FALSE)) {
data.add(new Object[]{withStartMenuShortcut,
withDesktopShortcut, withShortcutPrompt});
}
}
}
return data;
}
@Test
public void test() {
PackageTest test = new PackageTest()
.forTypes(PackageType.WINDOWS)
.configureHelloApp();
test.addInitializer(JPackageCommand::setFakeRuntime);
test.addInitializer(this::setPackageName);
if (withShortcutPrompt) {
test.addInitializer(cmd -> cmd.addArgument("--win-shortcut-prompt"));
}
if (withStartMenuShortcut) {
test.addInitializer(cmd -> cmd.addArgument("--win-menu"));
}
if (withDesktopShortcut) {
test.addInitializer(cmd -> cmd.addArgument("--win-shortcut"));
}
test.run();
}
private void setPackageName(JPackageCommand cmd) {
StringBuilder sb = new StringBuilder(cmd.name());
sb.append("With");
if (withShortcutPrompt) {
sb.append("ShortcutPrompt");
}
if (withStartMenuShortcut) {
sb.append("StartMenu");
}
if (withDesktopShortcut) {
sb.append("Desktop");
}
cmd.setArgumentValue("--name", sb.toString());
}
private final boolean withStartMenuShortcut;
private final boolean withDesktopShortcut;
private final boolean withShortcutPrompt;
}