8233636 : Make jpackage an incubator and remove tool provider implementation JDK-8200758-branch
authorherrick
Fri, 08 Nov 2019 14:53:03 -0500
branchJDK-8200758-branch
changeset 58994 b09ba68c6a19
parent 58993 b5e1baa9d2c3
child 58995 de1413ae214c
8233636 : Make jpackage an incubator and remove tool provider implementation Reviewed-by: asemenyuk, almatvee, kcr
make/CompileJavaModules.gmk
make/common/Modules.gmk
make/launcher/Launcher-jdk.incubator.jpackage.gmk
make/launcher/Launcher-jdk.jpackage.gmk
make/lib/Lib-jdk.incubator.jpackage.gmk
make/lib/Lib-jdk.jpackage.gmk
src/java.base/share/classes/module-info.java
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/DesktopIntegration.java
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LibProvidersLookup.java
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppBundler.java
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppImageBuilder.java
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxDebBundler.java
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxRpmBundler.java
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/PackageProperty.java
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources.properties
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_ja.properties
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_zh_CN.properties
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/java32.png
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.control
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.copyright
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.desktop
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.postinst
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.postrm
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.preinst
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.prerm
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.spec
src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/utils.sh
src/jdk.incubator.jpackage/linux/classes/module-info.java.extra
src/jdk.incubator.jpackage/linux/native/jpackageapplauncher/launcher.cpp
src/jdk.incubator.jpackage/linux/native/libapplauncher/LinuxPlatform.cpp
src/jdk.incubator.jpackage/linux/native/libapplauncher/LinuxPlatform.h
src/jdk.incubator.jpackage/linux/native/libapplauncher/PlatformDefs.h
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/EnumeratedBundlerParam.java
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppBundler.java
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppStoreBundler.java
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacBaseInstallerBundler.java
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacCertificate.java
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacDmgBundler.java
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacPkgBundler.java
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/DMGsetup.scpt
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/Info-lite.plist.template
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacAppStore.entitlements
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacAppStore_Inherit.entitlements
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacResources.properties
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacResources_ja.properties
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacResources_zh_CN.properties
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/Runtime-Info.plist.template
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/background_dmg.png
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/background_pkg.png
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/java.icns
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/lic_template.plist
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/postinstall.template
src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/preinstall.template
src/jdk.incubator.jpackage/macosx/classes/module-info.java.extra
src/jdk.incubator.jpackage/macosx/native/jpackageapplauncher/main.m
src/jdk.incubator.jpackage/macosx/native/libapplauncher/MacPlatform.h
src/jdk.incubator.jpackage/macosx/native/libapplauncher/MacPlatform.mm
src/jdk.incubator.jpackage/macosx/native/libapplauncher/PlatformDefs.h
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/ToolProviderFactory.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractAppImageBuilder.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractBundler.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractImageBundler.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AddLauncherArguments.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageFile.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ApplicationLayout.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ArgAction.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Arguments.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/BasicBundlers.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/BundleParams.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Bundler.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/BundlerParamInfo.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Bundlers.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/CLIHelp.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ConfigException.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/DeployParams.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/DottedVersion.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Executor.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/FileAssociation.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/I18N.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/IOUtils.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/JLinkBundlerHelper.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/JPackageToolProvider.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Log.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ModFile.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/OverridableResource.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/PackagerException.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/PathGroup.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Platform.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/PlatformPackage.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/RelativeFileSet.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ScriptRunner.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/StandardBundlerParam.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ToolValidator.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ValidOptions.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/HelpResources.properties
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/HelpResources_ja.properties
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/HelpResources_zh_CN.properties
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/MainResources.properties
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/MainResources_ja.properties
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/MainResources_zh_CN.properties
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/ResourceLocator.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/main/CommandLine.java
src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/main/Main.java
src/jdk.incubator.jpackage/share/classes/module-info.java
src/jdk.incubator.jpackage/share/native/libapplauncher/FileAttributes.h
src/jdk.incubator.jpackage/share/native/libapplauncher/FilePath.h
src/jdk.incubator.jpackage/share/native/libapplauncher/Helpers.cpp
src/jdk.incubator.jpackage/share/native/libapplauncher/Helpers.h
src/jdk.incubator.jpackage/share/native/libapplauncher/IniFile.cpp
src/jdk.incubator.jpackage/share/native/libapplauncher/IniFile.h
src/jdk.incubator.jpackage/share/native/libapplauncher/JavaVirtualMachine.cpp
src/jdk.incubator.jpackage/share/native/libapplauncher/JavaVirtualMachine.h
src/jdk.incubator.jpackage/share/native/libapplauncher/Library.cpp
src/jdk.incubator.jpackage/share/native/libapplauncher/Library.h
src/jdk.incubator.jpackage/share/native/libapplauncher/Macros.cpp
src/jdk.incubator.jpackage/share/native/libapplauncher/Macros.h
src/jdk.incubator.jpackage/share/native/libapplauncher/Messages.cpp
src/jdk.incubator.jpackage/share/native/libapplauncher/Messages.h
src/jdk.incubator.jpackage/share/native/libapplauncher/OrderedMap.h
src/jdk.incubator.jpackage/share/native/libapplauncher/Package.cpp
src/jdk.incubator.jpackage/share/native/libapplauncher/Package.h
src/jdk.incubator.jpackage/share/native/libapplauncher/Platform.cpp
src/jdk.incubator.jpackage/share/native/libapplauncher/Platform.h
src/jdk.incubator.jpackage/share/native/libapplauncher/PlatformString.cpp
src/jdk.incubator.jpackage/share/native/libapplauncher/PlatformString.h
src/jdk.incubator.jpackage/share/native/libapplauncher/Properties.h
src/jdk.incubator.jpackage/share/native/libapplauncher/PropertyFile.cpp
src/jdk.incubator.jpackage/share/native/libapplauncher/PropertyFile.h
src/jdk.incubator.jpackage/share/native/libapplauncher/main.cpp
src/jdk.incubator.jpackage/unix/native/libapplauncher/FileAttribute.h
src/jdk.incubator.jpackage/unix/native/libapplauncher/FileAttributes.cpp
src/jdk.incubator.jpackage/unix/native/libapplauncher/FilePath.cpp
src/jdk.incubator.jpackage/unix/native/libapplauncher/PosixPlatform.cpp
src/jdk.incubator.jpackage/unix/native/libapplauncher/PosixPlatform.h
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinAppBundler.java
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinExeBundler.java
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsAppImageBuilder.java
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsBundlerParam.java
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsDefender.java
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsRegistry.java
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixPipeline.java
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixSourcesBuilder.java
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixTool.java
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/MsiInstallerStrings_en.wxl
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/MsiInstallerStrings_ja.wxl
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/WinLauncher.template
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/WinResources.properties
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/WinResources_ja.properties
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/WinResources_zh_CN.properties
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/java48.ico
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/main.wxs
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/overrides.wxi
src/jdk.incubator.jpackage/windows/classes/module-info.java.extra
src/jdk.incubator.jpackage/windows/native/jpackageapplauncher/WinLauncher.cpp
src/jdk.incubator.jpackage/windows/native/libapplauncher/DllMain.cpp
src/jdk.incubator.jpackage/windows/native/libapplauncher/FileAttribute.h
src/jdk.incubator.jpackage/windows/native/libapplauncher/FilePath.cpp
src/jdk.incubator.jpackage/windows/native/libapplauncher/PlatformDefs.h
src/jdk.incubator.jpackage/windows/native/libapplauncher/WindowsPlatform.cpp
src/jdk.incubator.jpackage/windows/native/libapplauncher/WindowsPlatform.h
src/jdk.incubator.jpackage/windows/native/libjpackage/ByteBuffer.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/ByteBuffer.h
src/jdk.incubator.jpackage/windows/native/libjpackage/ErrorHandling.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/ErrorHandling.h
src/jdk.incubator.jpackage/windows/native/libjpackage/FileUtils.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/FileUtils.h
src/jdk.incubator.jpackage/windows/native/libjpackage/IconSwap.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/IconSwap.h
src/jdk.incubator.jpackage/windows/native/libjpackage/Log.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/Log.h
src/jdk.incubator.jpackage/windows/native/libjpackage/ResourceEditor.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/ResourceEditor.h
src/jdk.incubator.jpackage/windows/native/libjpackage/SourceCodePos.h
src/jdk.incubator.jpackage/windows/native/libjpackage/SysInfo.h
src/jdk.incubator.jpackage/windows/native/libjpackage/UniqueHandle.h
src/jdk.incubator.jpackage/windows/native/libjpackage/Utils.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/Utils.h
src/jdk.incubator.jpackage/windows/native/libjpackage/VersionInfoSwap.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/VersionInfoSwap.h
src/jdk.incubator.jpackage/windows/native/libjpackage/WinErrorHandling.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/WinErrorHandling.h
src/jdk.incubator.jpackage/windows/native/libjpackage/WinSysInfo.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/WinSysInfo.h
src/jdk.incubator.jpackage/windows/native/libjpackage/WindowsRegistry.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/jpackage.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/tstrings.cpp
src/jdk.incubator.jpackage/windows/native/libjpackage/tstrings.h
src/jdk.incubator.jpackage/windows/native/libwixhelper/libwixhelper.cpp
src/jdk.incubator.jpackage/windows/native/msiwrapper/Executor.cpp
src/jdk.incubator.jpackage/windows/native/msiwrapper/Executor.h
src/jdk.incubator.jpackage/windows/native/msiwrapper/MsiWrapper.cpp
src/jdk.incubator.jpackage/windows/native/msiwrapper/Resources.cpp
src/jdk.incubator.jpackage/windows/native/msiwrapper/Resources.h
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LibProvidersLookup.java
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppBundler.java
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebBundler.java
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBundler.java
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxRpmBundler.java
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/PackageProperty.java
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/java32.png
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.control
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.copyright
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.desktop
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.postinst
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.postrm
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.preinst
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.prerm
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.spec
src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/utils.sh
src/jdk.jpackage/linux/classes/module-info.java.extra
src/jdk.jpackage/linux/native/jpackageapplauncher/launcher.cpp
src/jdk.jpackage/linux/native/libapplauncher/LinuxPlatform.cpp
src/jdk.jpackage/linux/native/libapplauncher/LinuxPlatform.h
src/jdk.jpackage/linux/native/libapplauncher/PlatformDefs.h
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/EnumeratedBundlerParam.java
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppStoreBundler.java
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacCertificate.java
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgBundler.java
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/DMGsetup.scpt
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/Info-lite.plist.template
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacAppStore.entitlements
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacAppStore_Inherit.entitlements
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/Runtime-Info.plist.template
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/background_dmg.png
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/background_pkg.png
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/java.icns
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/lic_template.plist
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/postinstall.template
src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/preinstall.template
src/jdk.jpackage/macosx/classes/module-info.java.extra
src/jdk.jpackage/macosx/native/jpackageapplauncher/main.m
src/jdk.jpackage/macosx/native/libapplauncher/MacPlatform.h
src/jdk.jpackage/macosx/native/libapplauncher/MacPlatform.mm
src/jdk.jpackage/macosx/native/libapplauncher/PlatformDefs.h
src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractAppImageBuilder.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractBundler.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractImageBundler.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/AddLauncherArguments.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationLayout.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/ArgAction.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/BasicBundlers.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundleParams.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/Bundler.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundlerParamInfo.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/Bundlers.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/CLIHelp.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/ConfigException.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/DeployParams.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/DottedVersion.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/Executor.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/FileAssociation.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/I18N.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkBundlerHelper.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/JPackageToolProvider.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/Log.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/ModFile.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/PackagerException.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/PathGroup.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/Platform.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/PlatformPackage.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/RelativeFileSet.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/ScriptRunner.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/ToolValidator.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/ValidOptions.java
src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties
src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_ja.properties
src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_zh_CN.properties
src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources.properties
src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties
src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties
src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/ResourceLocator.java
src/jdk.jpackage/share/classes/jdk/jpackage/main/CommandLine.java
src/jdk.jpackage/share/classes/jdk/jpackage/main/Main.java
src/jdk.jpackage/share/classes/module-info.java
src/jdk.jpackage/share/native/libapplauncher/FileAttributes.h
src/jdk.jpackage/share/native/libapplauncher/FilePath.h
src/jdk.jpackage/share/native/libapplauncher/Helpers.cpp
src/jdk.jpackage/share/native/libapplauncher/Helpers.h
src/jdk.jpackage/share/native/libapplauncher/IniFile.cpp
src/jdk.jpackage/share/native/libapplauncher/IniFile.h
src/jdk.jpackage/share/native/libapplauncher/JavaVirtualMachine.cpp
src/jdk.jpackage/share/native/libapplauncher/JavaVirtualMachine.h
src/jdk.jpackage/share/native/libapplauncher/Library.cpp
src/jdk.jpackage/share/native/libapplauncher/Library.h
src/jdk.jpackage/share/native/libapplauncher/Macros.cpp
src/jdk.jpackage/share/native/libapplauncher/Macros.h
src/jdk.jpackage/share/native/libapplauncher/Messages.cpp
src/jdk.jpackage/share/native/libapplauncher/Messages.h
src/jdk.jpackage/share/native/libapplauncher/OrderedMap.h
src/jdk.jpackage/share/native/libapplauncher/Package.cpp
src/jdk.jpackage/share/native/libapplauncher/Package.h
src/jdk.jpackage/share/native/libapplauncher/Platform.cpp
src/jdk.jpackage/share/native/libapplauncher/Platform.h
src/jdk.jpackage/share/native/libapplauncher/PlatformString.cpp
src/jdk.jpackage/share/native/libapplauncher/PlatformString.h
src/jdk.jpackage/share/native/libapplauncher/Properties.h
src/jdk.jpackage/share/native/libapplauncher/PropertyFile.cpp
src/jdk.jpackage/share/native/libapplauncher/PropertyFile.h
src/jdk.jpackage/share/native/libapplauncher/main.cpp
src/jdk.jpackage/unix/native/libapplauncher/FileAttribute.h
src/jdk.jpackage/unix/native/libapplauncher/FileAttributes.cpp
src/jdk.jpackage/unix/native/libapplauncher/FilePath.cpp
src/jdk.jpackage/unix/native/libapplauncher/PosixPlatform.cpp
src/jdk.jpackage/unix/native/libapplauncher/PosixPlatform.h
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinAppBundler.java
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsAppImageBuilder.java
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsBundlerParam.java
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsDefender.java
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsRegistry.java
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourcesBuilder.java
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_en.wxl
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinLauncher.template
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/java48.ico
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/main.wxs
src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/overrides.wxi
src/jdk.jpackage/windows/classes/module-info.java.extra
src/jdk.jpackage/windows/native/jpackageapplauncher/WinLauncher.cpp
src/jdk.jpackage/windows/native/libapplauncher/DllMain.cpp
src/jdk.jpackage/windows/native/libapplauncher/FileAttribute.h
src/jdk.jpackage/windows/native/libapplauncher/FilePath.cpp
src/jdk.jpackage/windows/native/libapplauncher/PlatformDefs.h
src/jdk.jpackage/windows/native/libapplauncher/WindowsPlatform.cpp
src/jdk.jpackage/windows/native/libapplauncher/WindowsPlatform.h
src/jdk.jpackage/windows/native/libjpackage/ByteBuffer.cpp
src/jdk.jpackage/windows/native/libjpackage/ByteBuffer.h
src/jdk.jpackage/windows/native/libjpackage/ErrorHandling.cpp
src/jdk.jpackage/windows/native/libjpackage/ErrorHandling.h
src/jdk.jpackage/windows/native/libjpackage/FileUtils.cpp
src/jdk.jpackage/windows/native/libjpackage/FileUtils.h
src/jdk.jpackage/windows/native/libjpackage/IconSwap.cpp
src/jdk.jpackage/windows/native/libjpackage/IconSwap.h
src/jdk.jpackage/windows/native/libjpackage/Log.cpp
src/jdk.jpackage/windows/native/libjpackage/Log.h
src/jdk.jpackage/windows/native/libjpackage/ResourceEditor.cpp
src/jdk.jpackage/windows/native/libjpackage/ResourceEditor.h
src/jdk.jpackage/windows/native/libjpackage/SourceCodePos.h
src/jdk.jpackage/windows/native/libjpackage/SysInfo.h
src/jdk.jpackage/windows/native/libjpackage/UniqueHandle.h
src/jdk.jpackage/windows/native/libjpackage/Utils.cpp
src/jdk.jpackage/windows/native/libjpackage/Utils.h
src/jdk.jpackage/windows/native/libjpackage/VersionInfoSwap.cpp
src/jdk.jpackage/windows/native/libjpackage/VersionInfoSwap.h
src/jdk.jpackage/windows/native/libjpackage/WinErrorHandling.cpp
src/jdk.jpackage/windows/native/libjpackage/WinErrorHandling.h
src/jdk.jpackage/windows/native/libjpackage/WinSysInfo.cpp
src/jdk.jpackage/windows/native/libjpackage/WinSysInfo.h
src/jdk.jpackage/windows/native/libjpackage/WindowsRegistry.cpp
src/jdk.jpackage/windows/native/libjpackage/jpackage.cpp
src/jdk.jpackage/windows/native/libjpackage/tstrings.cpp
src/jdk.jpackage/windows/native/libjpackage/tstrings.h
src/jdk.jpackage/windows/native/libwixhelper/libwixhelper.cpp
src/jdk.jpackage/windows/native/msiwrapper/Executor.cpp
src/jdk.jpackage/windows/native/msiwrapper/Executor.h
src/jdk.jpackage/windows/native/msiwrapper/MsiWrapper.cpp
src/jdk.jpackage/windows/native/msiwrapper/Resources.cpp
src/jdk.jpackage/windows/native/msiwrapper/Resources.h
test/jdk/tools/jpackage/helpers/JPackageHelper.java
test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java
test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java
test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java
test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java
test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/AppImageFileTest.java
test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/ApplicationLayoutTest.java
test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/CompareDottedVersionTest.java
test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/DeployParamsTest.java
test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/DottedVersionTest.java
test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/InvalidDottedVersionTest.java
test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/OverridableResourceTest.java
test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/PathGroupTest.java
test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/ToolValidatorTest.java
test/jdk/tools/jpackage/junit/jdk/jpackage/internal/AppImageFileTest.java
test/jdk/tools/jpackage/junit/jdk/jpackage/internal/ApplicationLayoutTest.java
test/jdk/tools/jpackage/junit/jdk/jpackage/internal/CompareDottedVersionTest.java
test/jdk/tools/jpackage/junit/jdk/jpackage/internal/DeployParamsTest.java
test/jdk/tools/jpackage/junit/jdk/jpackage/internal/DottedVersionTest.java
test/jdk/tools/jpackage/junit/jdk/jpackage/internal/InvalidDottedVersionTest.java
test/jdk/tools/jpackage/junit/jdk/jpackage/internal/OverridableResourceTest.java
test/jdk/tools/jpackage/junit/jdk/jpackage/internal/PathGroupTest.java
test/jdk/tools/jpackage/junit/jdk/jpackage/internal/ToolValidatorTest.java
test/jdk/tools/jpackage/junit/run_junit.sh
test/jdk/tools/jpackage/linux/AppCategoryTest.java
test/jdk/tools/jpackage/linux/LicenseTypeTest.java
test/jdk/tools/jpackage/linux/LinuxBundleNameTest.java
test/jdk/tools/jpackage/linux/LinuxResourceTest.java
test/jdk/tools/jpackage/linux/MaintainerTest.java
test/jdk/tools/jpackage/linux/PackageDepsTest.java
test/jdk/tools/jpackage/linux/ReleaseTest.java
test/jdk/tools/jpackage/linux/ShortcutHintTest.java
test/jdk/tools/jpackage/macosx/MacPropertiesTest.java
test/jdk/tools/jpackage/macosx/NameWithSpaceTest.java
test/jdk/tools/jpackage/macosx/SigningAppImageTest.java
test/jdk/tools/jpackage/macosx/SigningPackageTest.java
test/jdk/tools/jpackage/macosx/base/SigningCheck.java
test/jdk/tools/jpackage/share/AddLauncherModuleTest.java
test/jdk/tools/jpackage/share/AddLauncherTest.java
test/jdk/tools/jpackage/share/AddLaunchersTest.java
test/jdk/tools/jpackage/share/AdditionalLaunchersTest.java
test/jdk/tools/jpackage/share/AppImagePackageTest.java
test/jdk/tools/jpackage/share/ArgumentsTest.java
test/jdk/tools/jpackage/share/ErrorTest.java
test/jdk/tools/jpackage/share/FileAssociationsTest.java
test/jdk/tools/jpackage/share/IconTest.java
test/jdk/tools/jpackage/share/InstallDirTest.java
test/jdk/tools/jpackage/share/InvalidArgTest.java
test/jdk/tools/jpackage/share/JavaOptionsEqualsTest.java
test/jdk/tools/jpackage/share/JavaOptionsModuleTest.java
test/jdk/tools/jpackage/share/JavaOptionsTest.java
test/jdk/tools/jpackage/share/LicenseTest.java
test/jdk/tools/jpackage/share/MissingArgumentsTest.java
test/jdk/tools/jpackage/share/RuntimePackageTest.java
test/jdk/tools/jpackage/share/SimplePackageTest.java
test/jdk/tools/jpackage/share/jdk/jpackage/tests/AppVersionTest.java
test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java
test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java
test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest.java
test/jdk/tools/jpackage/windows/WinConsoleTest.java
test/jdk/tools/jpackage/windows/WinDirChooserTest.java
test/jdk/tools/jpackage/windows/WinMenuGroupTest.java
test/jdk/tools/jpackage/windows/WinMenuTest.java
test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java
test/jdk/tools/jpackage/windows/WinResourceTest.java
test/jdk/tools/jpackage/windows/WinScriptTest.java
test/jdk/tools/jpackage/windows/WinShortcutTest.java
test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java
--- a/make/CompileJavaModules.gmk	Wed Nov 06 07:20:07 2019 -0500
+++ b/make/CompileJavaModules.gmk	Fri Nov 08 14:53:03 2019 -0500
@@ -380,10 +380,10 @@
 
 ################################################################################
 
-jdk.jpackage_COPY += .gif .png .txt .spec .script .prerm .preinst .postrm .postinst .list .sh \
+jdk.incubator.jpackage_COPY += .gif .png .txt .spec .script .prerm .preinst .postrm .postinst .list .sh \
     .desktop .copyright .control .plist .template .icns .scpt .entitlements .wxs .wxl .wxi .ico .bmp
 
-jdk.jpackage_CLEAN += .properties
+jdk.incubator.jpackage_CLEAN += .properties
 
 ################################################################################
 
--- a/make/common/Modules.gmk	Wed Nov 06 07:20:07 2019 -0500
+++ b/make/common/Modules.gmk	Fri Nov 08 14:53:03 2019 -0500
@@ -128,8 +128,8 @@
 
 JRE_TOOL_MODULES += \
     jdk.jdwp.agent \
+    jdk.incubator.jpackage \
     jdk.pack \
-    jdk.jpackage \
     jdk.scripting.nashorn.shell \
     #
 
@@ -150,6 +150,7 @@
     jdk.editpad \
     jdk.hotspot.agent \
     jdk.httpserver \
+    jdk.incubator.jpackage \
     jdk.jartool \
     jdk.javadoc \
     jdk.jcmd \
@@ -170,7 +171,6 @@
     jdk.naming.rmi \
     jdk.net \
     jdk.pack \
-    jdk.jpackage \
     jdk.rmic \
     jdk.scripting.nashorn \
     jdk.sctp \
@@ -248,7 +248,7 @@
 # jpackage is only on windows, macosx, and linux
 
 ifeq ($(call isTargetOs, windows macosx linux), false)
-  MODULES_FILTER += jdk.jpackage
+  MODULES_FILTER += jdk.incubator.jpackage
 endif
 
 ################################################################################
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/launcher/Launcher-jdk.incubator.jpackage.gmk	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2018, 2019, 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.
+#
+
+include LauncherCommon.gmk
+
+$(eval $(call SetupBuildLauncher, jpackage, \
+    MAIN_CLASS := jdk.incubator.jpackage.main.Main, \
+))
--- a/make/launcher/Launcher-jdk.jpackage.gmk	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#
-# Copyright (c) 2018, 2019, 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.
-#
-
-include LauncherCommon.gmk
-
-$(eval $(call SetupBuildLauncher, jpackage, \
-    MAIN_CLASS := jdk.jpackage.main.Main, \
-))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/lib/Lib-jdk.incubator.jpackage.gmk	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,140 @@
+#
+# Copyright (c) 2018, 2019, 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.
+#
+
+include LibCommon.gmk
+
+################################################################################
+
+# Output app launcher library in resources dir, and symbols in the object dir
+$(eval $(call SetupJdkLibrary, BUILD_LIB_APPLAUNCHER, \
+    NAME := applauncher, \
+    OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \
+    SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libapplauncher, \
+    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+    OPTIMIZATION := LOW, \
+    CFLAGS := $(CXXFLAGS_JDKLIB), \
+    CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
+    LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
+        $(call SET_SHARED_LIBRARY_ORIGIN), \
+    LIBS := $(LIBCXX), \
+    LIBS_windows := user32.lib shell32.lib advapi32.lib ole32.lib, \
+    LIBS_linux := -ldl -lpthread, \
+    LIBS_macosx := -ldl -framework Cocoa, \
+))
+
+$(BUILD_LIB_APPLAUNCHER): $(call FindLib, java.base, java)
+
+TARGETS += $(BUILD_LIB_APPLAUNCHER)
+
+JPACKAGE_APPLAUNCHER_SRC := \
+    $(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/jpackageapplauncher
+
+# Output app launcher executable in resources dir, and symbols in the object dir
+$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \
+    NAME := jpackageapplauncher, \
+    OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \
+    SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncher, \
+    SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
+    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+    OPTIMIZATION := LOW, \
+    CFLAGS := $(CXXFLAGS_JDKEXE), \
+    CFLAGS_windows := -EHsc -DLAUNCHERC -DUNICODE -D_UNICODE, \
+    LDFLAGS := $(LDFLAGS_JDKEXE), \
+    LIBS_macosx := -framework Cocoa, \
+    LIBS := $(LIBCXX), \
+    LIBS_linux := -ldl, \
+    LIBS_windows := user32.lib shell32.lib advapi32.lib, \
+))
+
+TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE)
+
+################################################################################
+
+ifeq ($(call isTargetOs, windows), true)
+
+  $(eval $(call SetupJdkLibrary, BUILD_LIB_JPACKAGE, \
+      NAME := jpackage, \
+      OPTIMIZATION := LOW, \
+      CFLAGS := $(CXXFLAGS_JDKLIB), \
+      CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
+      LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
+          $(call SET_SHARED_LIBRARY_ORIGIN), \
+      LIBS := $(LIBCXX), \
+      LIBS_windows := user32.lib shell32.lib advapi32.lib ole32.lib, \
+  ))
+
+  TARGETS += $(BUILD_LIB_JPACKAGE)
+
+  # Build Wix custom action helper
+  # Output library in resources dir, and symbols in the object dir
+  $(eval $(call SetupJdkLibrary, BUILD_LIB_WIXHELPER, \
+      NAME := wixhelper, \
+      OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \
+      SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libwixhelper, \
+      OPTIMIZATION := LOW, \
+      CFLAGS := $(CXXFLAGS_JDKLIB), \
+      CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE -MT, \
+      LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \
+      LIBS := $(LIBCXX), \
+      LIBS_windows := msi.lib Shlwapi.lib User32.lib, \
+  ))
+
+  TARGETS += $(BUILD_LIB_WIXHELPER)
+
+  # Build exe installer wrapper for msi installer
+  $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_MSIWRAPPER, \
+      NAME := msiwrapper, \
+      OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \
+      SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/msiwrapper, \
+      SRC := $(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/msiwrapper, \
+      EXTRA_FILES := $(addprefix $(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/libjpackage/, \
+          FileUtils.cpp Log.cpp WinSysInfo.cpp tstrings.cpp WinErrorHandling.cpp ErrorHandling.cpp), \
+      CFLAGS := $(CXXFLAGS_JDKEXE) -MT \
+          $(addprefix -I$(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/, msiwrapper libjpackage), \
+      CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
+      LDFLAGS := $(LDFLAGS_JDKEXE), \
+      LIBS := $(LIBCXX), \
+  ))
+
+  TARGETS += $(BUILD_JPACKAGE_MSIWRAPPER)
+
+  # Build non-console version of launcher
+  $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHERWEXE, \
+      NAME := jpackageapplauncherw, \
+      OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \
+      SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \
+      SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
+      TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+      OPTIMIZATION := LOW, \
+      CFLAGS := $(CXXFLAGS_JDKEXE), \
+      CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
+      LDFLAGS := $(LDFLAGS_JDKEXE), \
+      LIBS := $(LIBCXX), \
+      LIBS_windows := user32.lib shell32.lib advapi32.lib, \
+  ))
+
+  TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE)
+
+endif
--- a/make/lib/Lib-jdk.jpackage.gmk	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-#
-# Copyright (c) 2018, 2019, 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.
-#
-
-include LibCommon.gmk
-
-################################################################################
-
-# Output app launcher library in resources dir, and symbols in the object dir
-$(eval $(call SetupJdkLibrary, BUILD_LIB_APPLAUNCHER, \
-    NAME := applauncher, \
-    OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/jpackage/internal/resources, \
-    SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libapplauncher, \
-    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
-    OPTIMIZATION := LOW, \
-    CFLAGS := $(CXXFLAGS_JDKLIB), \
-    CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
-    LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
-        $(call SET_SHARED_LIBRARY_ORIGIN), \
-    LIBS := $(LIBCXX), \
-    LIBS_windows := user32.lib shell32.lib advapi32.lib ole32.lib, \
-    LIBS_linux := -ldl -lpthread, \
-    LIBS_macosx := -ldl -framework Cocoa, \
-))
-
-$(BUILD_LIB_APPLAUNCHER): $(call FindLib, java.base, java)
-
-TARGETS += $(BUILD_LIB_APPLAUNCHER)
-
-JPACKAGE_APPLAUNCHER_SRC := \
-    $(TOPDIR)/src/jdk.jpackage/$(OPENJDK_TARGET_OS)/native/jpackageapplauncher
-
-# Output app launcher executable in resources dir, and symbols in the object dir
-$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \
-    NAME := jpackageapplauncher, \
-    OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/jpackage/internal/resources, \
-    SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncher, \
-    SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
-    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
-    OPTIMIZATION := LOW, \
-    CFLAGS := $(CXXFLAGS_JDKEXE), \
-    CFLAGS_windows := -EHsc -DLAUNCHERC -DUNICODE -D_UNICODE, \
-    LDFLAGS := $(LDFLAGS_JDKEXE), \
-    LIBS_macosx := -framework Cocoa, \
-    LIBS := $(LIBCXX), \
-    LIBS_linux := -ldl, \
-    LIBS_windows := user32.lib shell32.lib advapi32.lib, \
-))
-
-TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE)
-
-################################################################################
-
-ifeq ($(call isTargetOs, windows), true)
-
-  $(eval $(call SetupJdkLibrary, BUILD_LIB_JPACKAGE, \
-      NAME := jpackage, \
-      OPTIMIZATION := LOW, \
-      CFLAGS := $(CXXFLAGS_JDKLIB), \
-      CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
-      LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
-          $(call SET_SHARED_LIBRARY_ORIGIN), \
-      LIBS := $(LIBCXX), \
-      LIBS_windows := user32.lib shell32.lib advapi32.lib ole32.lib, \
-  ))
-
-  TARGETS += $(BUILD_LIB_JPACKAGE)
-
-  # Build Wix custom action helper
-  # Output library in resources dir, and symbols in the object dir
-  $(eval $(call SetupJdkLibrary, BUILD_LIB_WIXHELPER, \
-      NAME := wixhelper, \
-      OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/jpackage/internal/resources, \
-      SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libwixhelper, \
-      OPTIMIZATION := LOW, \
-      CFLAGS := $(CXXFLAGS_JDKLIB), \
-      CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE -MT, \
-      LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \
-      LIBS := $(LIBCXX), \
-      LIBS_windows := msi.lib Shlwapi.lib User32.lib, \
-  ))
-
-  TARGETS += $(BUILD_LIB_WIXHELPER)
-
-  # Build exe installer wrapper for msi installer
-  $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_MSIWRAPPER, \
-      NAME := msiwrapper, \
-      OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/jpackage/internal/resources, \
-      SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/msiwrapper, \
-      SRC := $(TOPDIR)/src/jdk.jpackage/$(OPENJDK_TARGET_OS)/native/msiwrapper, \
-      EXTRA_FILES := $(addprefix $(TOPDIR)/src/jdk.jpackage/$(OPENJDK_TARGET_OS)/native/libjpackage/, \
-          FileUtils.cpp Log.cpp WinSysInfo.cpp tstrings.cpp WinErrorHandling.cpp ErrorHandling.cpp), \
-      CFLAGS := $(CXXFLAGS_JDKEXE) -MT \
-          $(addprefix -I$(TOPDIR)/src/jdk.jpackage/$(OPENJDK_TARGET_OS)/native/, msiwrapper libjpackage), \
-      CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
-      LDFLAGS := $(LDFLAGS_JDKEXE), \
-      LIBS := $(LIBCXX), \
-  ))
-
-  TARGETS += $(BUILD_JPACKAGE_MSIWRAPPER)
-
-  # Build non-console version of launcher
-  $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHERWEXE, \
-      NAME := jpackageapplauncherw, \
-      OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/jpackage/internal/resources, \
-      SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \
-      SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
-      TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
-      OPTIMIZATION := LOW, \
-      CFLAGS := $(CXXFLAGS_JDKEXE), \
-      CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
-      LDFLAGS := $(LDFLAGS_JDKEXE), \
-      LIBS := $(LIBCXX), \
-      LIBS_windows := user32.lib shell32.lib advapi32.lib, \
-  ))
-
-  TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE)
-
-endif
--- a/src/java.base/share/classes/module-info.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/src/java.base/share/classes/module-info.java	Fri Nov 08 14:53:03 2019 -0500
@@ -204,7 +204,7 @@
         jdk.jartool,
         jdk.jfr,
         jdk.jlink,
-        jdk.jpackage;
+        jdk.incubator.jpackage;
     exports jdk.internal.perf to
         java.management,
         jdk.management.agent,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/DesktopIntegration.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.imageio.ImageIO;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import static jdk.incubator.jpackage.internal.LinuxAppBundler.ICON_PNG;
+import static jdk.incubator.jpackage.internal.LinuxAppImageBuilder.DEFAULT_ICON;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+/**
+ * Helper to create files for desktop integration.
+ */
+final class DesktopIntegration {
+
+    static final String DESKTOP_COMMANDS_INSTALL = "DESKTOP_COMMANDS_INSTALL";
+    static final String DESKTOP_COMMANDS_UNINSTALL = "DESKTOP_COMMANDS_UNINSTALL";
+    static final String UTILITY_SCRIPTS = "UTILITY_SCRIPTS";
+
+    DesktopIntegration(PlatformPackage thePackage,
+            Map<String, ? super Object> params) {
+
+        associations = FileAssociation.fetchFrom(params).stream()
+                .filter(fa -> !fa.mimeTypes.isEmpty())
+                .map(LinuxFileAssociation::new)
+                .collect(Collectors.toUnmodifiableList());
+
+        launchers = ADD_LAUNCHERS.fetchFrom(params);
+
+        this.thePackage = thePackage;
+
+        final File customIconFile = ICON_PNG.fetchFrom(params);
+
+        iconResource = createResource(DEFAULT_ICON, params)
+                .setCategory(I18N.getString("resource.menu-icon"))
+                .setExternal(customIconFile);
+        desktopFileResource = createResource("template.desktop", params)
+                .setCategory(I18N.getString("resource.menu-shortcut-descriptor"))
+                .setPublicName(APP_NAME.fetchFrom(params) + ".desktop");
+
+        // XDG recommends to use vendor prefix in desktop file names as xdg
+        // commands copy files to system directories.
+        // Package name should be a good prefix.
+        final String desktopFileName = String.format("%s-%s.desktop",
+                    thePackage.name(), APP_NAME.fetchFrom(params));
+        final String mimeInfoFileName = String.format("%s-%s-MimeInfo.xml",
+                    thePackage.name(), APP_NAME.fetchFrom(params));
+
+        mimeInfoFile = new DesktopFile(mimeInfoFileName);
+
+        if (!associations.isEmpty() || SHORTCUT_HINT.fetchFrom(params) || customIconFile != null) {
+            //
+            // Create primary .desktop file if one of conditions is met:
+            // - there are file associations configured
+            // - user explicitely requested to create a shortcut
+            // - custom icon specified
+            //
+            desktopFile = new DesktopFile(desktopFileName);
+            iconFile = new DesktopFile(APP_NAME.fetchFrom(params)
+                    + IOUtils.getSuffix(Path.of(DEFAULT_ICON)));
+        } else {
+            desktopFile = null;
+            iconFile = null;
+        }
+
+        desktopFileData = Collections.unmodifiableMap(
+                createDataForDesktopFile(params));
+
+        nestedIntegrations = launchers.stream().map(
+                launcherParams -> new DesktopIntegration(thePackage,
+                        launcherParams)).collect(Collectors.toList());
+    }
+
+    List<String> requiredPackages() {
+        return Stream.of(List.of(this), nestedIntegrations).flatMap(
+                List::stream).map(DesktopIntegration::requiredPackagesSelf).flatMap(
+                List::stream).distinct().collect(Collectors.toList());
+    }
+
+    Map<String, String> create() throws IOException {
+        associations.forEach(assoc -> assoc.data.verify());
+
+        if (iconFile != null) {
+            // Create application icon file.
+            iconResource.saveToFile(iconFile.srcPath());
+        }
+
+        Map<String, String> data = new HashMap<>(desktopFileData);
+
+        final ShellCommands shellCommands;
+        if (desktopFile != null) {
+            // Create application desktop description file.
+            createDesktopFile(data);
+
+            // Shell commands will be created only if desktop file
+            // should be installed.
+            shellCommands = new ShellCommands();
+        } else {
+            shellCommands = null;
+        }
+
+        if (!associations.isEmpty()) {
+            // Create XML file with mime types corresponding to file associations.
+            createFileAssociationsMimeInfoFile();
+
+            shellCommands.setFileAssociations();
+
+            // Create icon files corresponding to file associations
+            addFileAssociationIconFiles(shellCommands);
+        }
+
+        // Create shell commands to install/uninstall integration with desktop of the app.
+        if (shellCommands != null) {
+            shellCommands.applyTo(data);
+        }
+
+        boolean needCleanupScripts = !associations.isEmpty();
+
+        // Take care of additional launchers if there are any.
+        // Process every additional launcher as the main application launcher.
+        // Collect shell commands to install/uninstall integration with desktop
+        // of the additional launchers and append them to the corresponding
+        // commands of the main launcher.
+        List<String> installShellCmds = new ArrayList<>(Arrays.asList(
+                data.get(DESKTOP_COMMANDS_INSTALL)));
+        List<String> uninstallShellCmds = new ArrayList<>(Arrays.asList(
+                data.get(DESKTOP_COMMANDS_UNINSTALL)));
+        for (var integration: nestedIntegrations) {
+            if (!integration.associations.isEmpty()) {
+                needCleanupScripts = true;
+            }
+
+            Map<String, String> launcherData = integration.create();
+
+            installShellCmds.add(launcherData.get(DESKTOP_COMMANDS_INSTALL));
+            uninstallShellCmds.add(launcherData.get(
+                    DESKTOP_COMMANDS_UNINSTALL));
+        }
+
+        data.put(DESKTOP_COMMANDS_INSTALL, stringifyShellCommands(
+                installShellCmds));
+        data.put(DESKTOP_COMMANDS_UNINSTALL, stringifyShellCommands(
+                uninstallShellCmds));
+
+        if (needCleanupScripts) {
+            // Pull in utils.sh scrips library.
+            try (InputStream is = OverridableResource.readDefault("utils.sh");
+                    InputStreamReader isr = new InputStreamReader(is);
+                    BufferedReader reader = new BufferedReader(isr)) {
+                data.put(UTILITY_SCRIPTS, reader.lines().collect(
+                        Collectors.joining(System.lineSeparator())));
+            }
+        } else {
+            data.put(UTILITY_SCRIPTS, "");
+        }
+
+        return data;
+    }
+
+    private List<String> requiredPackagesSelf() {
+        if (desktopFile != null) {
+            return List.of("xdg-utils");
+        }
+        return Collections.emptyList();
+    }
+
+    private Map<String, String> createDataForDesktopFile(
+            Map<String, ? super Object> params) {
+        Map<String, String> data = new HashMap<>();
+        data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
+        data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
+        data.put("APPLICATION_ICON",
+                iconFile != null ? iconFile.installPath().toString() : null);
+        data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params));
+        data.put("APPLICATION_LAUNCHER",
+                thePackage.installedApplicationLayout().launchersDirectory().resolve(
+                        LinuxAppImageBuilder.getLauncherName(params)).toString());
+
+        return data;
+    }
+
+    /**
+     * Shell commands to integrate something with desktop.
+     */
+    private class ShellCommands {
+
+        ShellCommands() {
+            registerIconCmds = new ArrayList<>();
+            unregisterIconCmds = new ArrayList<>();
+
+            registerDesktopFileCmd = String.join(" ", "xdg-desktop-menu",
+                    "install", desktopFile.installPath().toString());
+            unregisterDesktopFileCmd = String.join(" ", "xdg-desktop-menu",
+                    "uninstall", desktopFile.installPath().toString());
+        }
+
+        void setFileAssociations() {
+            registerFileAssociationsCmd = String.join(" ", "xdg-mime",
+                    "install",
+                    mimeInfoFile.installPath().toString());
+            unregisterFileAssociationsCmd = String.join(" ", "xdg-mime",
+                    "uninstall", mimeInfoFile.installPath().toString());
+
+            //
+            // Add manual cleanup of system files to get rid of
+            // the default mime type handlers.
+            //
+            // Even after mime type is unregisterd with `xdg-mime uninstall`
+            // command and desktop file deleted with `xdg-desktop-menu uninstall`
+            // command, records in
+            // `/usr/share/applications/defaults.list` (Ubuntu 16) or
+            // `/usr/local/share/applications/defaults.list` (OracleLinux 7)
+            // files remain referencing deleted mime time and deleted
+            // desktop file which makes `xdg-mime query default` output name
+            // of non-existing desktop file.
+            //
+            String cleanUpCommand = String.join(" ",
+                    "uninstall_default_mime_handler",
+                    desktopFile.installPath().getFileName().toString(),
+                    String.join(" ", getMimeTypeNamesFromFileAssociations()));
+
+            unregisterFileAssociationsCmd = stringifyShellCommands(
+                    unregisterFileAssociationsCmd, cleanUpCommand);
+        }
+
+        void addIcon(String mimeType, Path iconFile) {
+            addIcon(mimeType, iconFile, getSquareSizeOfImage(iconFile.toFile()));
+        }
+
+        void addIcon(String mimeType, Path iconFile, int imgSize) {
+            imgSize = normalizeIconSize(imgSize);
+            final String dashMime = mimeType.replace('/', '-');
+            registerIconCmds.add(String.join(" ", "xdg-icon-resource",
+                    "install", "--context", "mimetypes", "--size",
+                    Integer.toString(imgSize), iconFile.toString(), dashMime));
+            unregisterIconCmds.add(String.join(" ", "xdg-icon-resource",
+                    "uninstall", dashMime, "--size", Integer.toString(imgSize)));
+        }
+
+        void applyTo(Map<String, String> data) {
+            List<String> cmds = new ArrayList<>();
+
+            cmds.add(registerDesktopFileCmd);
+            cmds.add(registerFileAssociationsCmd);
+            cmds.addAll(registerIconCmds);
+            data.put(DESKTOP_COMMANDS_INSTALL, stringifyShellCommands(cmds));
+
+            cmds.clear();
+            cmds.add(unregisterDesktopFileCmd);
+            cmds.add(unregisterFileAssociationsCmd);
+            cmds.addAll(unregisterIconCmds);
+            data.put(DESKTOP_COMMANDS_UNINSTALL, stringifyShellCommands(cmds));
+        }
+
+        private String registerDesktopFileCmd;
+        private String unregisterDesktopFileCmd;
+
+        private String registerFileAssociationsCmd;
+        private String unregisterFileAssociationsCmd;
+
+        private List<String> registerIconCmds;
+        private List<String> unregisterIconCmds;
+    }
+
+    /**
+     * Desktop integration file. xml, icon, etc.
+     * Resides somewhere in application installation tree.
+     * Has two paths:
+     *  - path where it should be placed at package build time;
+     *  - path where it should be installed by package manager;
+     */
+    private class DesktopFile {
+
+        DesktopFile(String fileName) {
+            installPath = thePackage
+                    .installedApplicationLayout()
+                    .destktopIntegrationDirectory().resolve(fileName);
+            srcPath = thePackage
+                    .sourceApplicationLayout()
+                    .destktopIntegrationDirectory().resolve(fileName);
+        }
+
+        private final Path installPath;
+        private final Path srcPath;
+
+        Path installPath() {
+            return installPath;
+        }
+
+        Path srcPath() {
+            return srcPath;
+        }
+    }
+
+    private void appendFileAssociation(XMLStreamWriter xml,
+            FileAssociation assoc) throws XMLStreamException {
+
+        for (var mimeType : assoc.mimeTypes) {
+            xml.writeStartElement("mime-type");
+            xml.writeAttribute("type", mimeType);
+
+            final String description = assoc.description;
+            if (description != null && !description.isEmpty()) {
+                xml.writeStartElement("comment");
+                xml.writeCharacters(description);
+                xml.writeEndElement();
+            }
+
+            for (String ext : assoc.extensions) {
+                xml.writeStartElement("glob");
+                xml.writeAttribute("pattern", "*." + ext);
+                xml.writeEndElement();
+            }
+
+            xml.writeEndElement();
+        }
+    }
+
+    private void createFileAssociationsMimeInfoFile() throws IOException {
+        IOUtils.createXml(mimeInfoFile.srcPath(), xml -> {
+            xml.writeStartElement("mime-info");
+            xml.writeDefaultNamespace(
+                    "http://www.freedesktop.org/standards/shared-mime-info");
+
+            for (var assoc : associations) {
+                appendFileAssociation(xml, assoc.data);
+            }
+
+            xml.writeEndElement();
+        });
+    }
+
+    private void addFileAssociationIconFiles(ShellCommands shellCommands)
+            throws IOException {
+        Set<String> processedMimeTypes = new HashSet<>();
+        for (var assoc : associations) {
+            if (assoc.iconSize <= 0) {
+                // No icon.
+                continue;
+            }
+
+            for (var mimeType : assoc.data.mimeTypes) {
+                if (processedMimeTypes.contains(mimeType)) {
+                    continue;
+                }
+
+                processedMimeTypes.add(mimeType);
+
+                // Create icon name for mime type from mime type.
+                DesktopFile faIconFile = new DesktopFile(mimeType.replace(
+                        File.separatorChar, '-') + IOUtils.getSuffix(
+                                assoc.data.iconPath));
+
+                IOUtils.copyFile(assoc.data.iconPath.toFile(),
+                        faIconFile.srcPath().toFile());
+
+                shellCommands.addIcon(mimeType, faIconFile.installPath(),
+                        assoc.iconSize);
+            }
+        }
+    }
+
+    private void createDesktopFile(Map<String, String> data) throws IOException {
+        List<String> mimeTypes = getMimeTypeNamesFromFileAssociations();
+        data.put("DESKTOP_MIMES", "MimeType=" + String.join(";", mimeTypes));
+
+        // prepare desktop shortcut
+        desktopFileResource
+                .setSubstitutionData(data)
+                .saveToFile(desktopFile.srcPath());
+    }
+
+    private List<String> getMimeTypeNamesFromFileAssociations() {
+        return associations.stream()
+                .map(fa -> fa.data.mimeTypes)
+                .flatMap(List::stream)
+                .collect(Collectors.toUnmodifiableList());
+    }
+
+    private static int getSquareSizeOfImage(File f) {
+        try {
+            BufferedImage bi = ImageIO.read(f);
+            return Math.max(bi.getWidth(), bi.getHeight());
+        } catch (IOException e) {
+            Log.verbose(e);
+        }
+        return 0;
+    }
+
+    private static int normalizeIconSize(int iconSize) {
+        // If register icon with "uncommon" size, it will be ignored.
+        // So find the best matching "common" size.
+        List<Integer> commonIconSizes = List.of(16, 22, 32, 48, 64, 128);
+
+        int idx = Collections.binarySearch(commonIconSizes, iconSize);
+        if (idx < 0) {
+            // Given icon size is greater than the largest common icon size.
+            return commonIconSizes.get(commonIconSizes.size() - 1);
+        }
+
+        if (idx == 0) {
+            // Given icon size is less or equal than the smallest common icon size.
+            return commonIconSizes.get(idx);
+        }
+
+        int commonIconSize = commonIconSizes.get(idx);
+        if (iconSize < commonIconSize) {
+            // It is better to scale down original icon than to scale it up for
+            // better visual quality.
+            commonIconSize = commonIconSizes.get(idx - 1);
+        }
+
+        return commonIconSize;
+    }
+
+    private static String stringifyShellCommands(String... commands) {
+        return stringifyShellCommands(Arrays.asList(commands));
+    }
+
+    private static String stringifyShellCommands(List<String> commands) {
+        return String.join(System.lineSeparator(), commands.stream().filter(
+                s -> s != null && !s.isEmpty()).collect(Collectors.toList()));
+    }
+
+    private static class LinuxFileAssociation {
+        LinuxFileAssociation(FileAssociation fa) {
+            this.data = fa;
+            if (fa.iconPath != null && Files.isReadable(fa.iconPath)) {
+                iconSize = getSquareSizeOfImage(fa.iconPath.toFile());
+            } else {
+                iconSize = -1;
+            }
+        }
+
+        final FileAssociation data;
+        final int iconSize;
+    }
+
+    private final PlatformPackage thePackage;
+
+    private final List<LinuxFileAssociation> associations;
+
+    private final List<Map<String, ? super Object>> launchers;
+
+    private final OverridableResource iconResource;
+    private final OverridableResource desktopFileResource;
+
+    private final DesktopFile mimeInfoFile;
+    private final DesktopFile desktopFile;
+    private final DesktopFile iconFile;
+
+    private final List<DesktopIntegration> nestedIntegrations;
+
+    private final Map<String, String> desktopFileData;
+
+    private static final BundlerParamInfo<String> MENU_GROUP =
+        new StandardBundlerParam<>(
+                Arguments.CLIOptions.LINUX_MENU_GROUP.getId(),
+                String.class,
+                params -> I18N.getString("param.menu-group.default"),
+                (s, p) -> s
+        );
+
+    private static final StandardBundlerParam<Boolean> SHORTCUT_HINT =
+        new StandardBundlerParam<>(
+                Arguments.CLIOptions.LINUX_SHORTCUT_HINT.getId(),
+                Boolean.class,
+                params -> false,
+                (s, p) -> (s == null || "null".equalsIgnoreCase(s))
+                        ? false : Boolean.valueOf(s)
+        );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LibProvidersLookup.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.function.Predicate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Builds list of packages providing dynamic libraries for the given set of files.
+ */
+final public class LibProvidersLookup {
+    static boolean supported() {
+        return (new ToolValidator(TOOL_LDD).validate() == null);
+    }
+
+    public LibProvidersLookup() {
+    }
+
+    LibProvidersLookup setPackageLookup(PackageLookup v) {
+        packageLookup = v;
+        return this;
+    }
+
+    List<String> execute(Path root) throws IOException {
+        // Get the list of files in the root for which to look up for needed shared libraries
+        List<Path> allPackageFiles;
+        try (Stream<Path> stream = Files.walk(root)) {
+            allPackageFiles = stream.filter(Files::isRegularFile).filter(
+                    LibProvidersLookup::canDependOnLibs).collect(
+                    Collectors.toList());
+        }
+
+        Collection<Path> neededLibs = getNeededLibsForFiles(allPackageFiles);
+
+        // Get the list of unique package names.
+        List<String> neededPackages = neededLibs.stream().map(libPath -> {
+            try {
+                List<String> packageNames = packageLookup.apply(libPath).filter(
+                        Objects::nonNull).filter(Predicate.not(String::isBlank)).distinct().collect(
+                        Collectors.toList());
+                Log.verbose(String.format("%s is provided by %s", libPath, packageNames));
+                return packageNames;
+            } catch (IOException ex) {
+                // Ignore and keep going
+                Log.verbose(ex);
+                List<String> packageNames = Collections.emptyList();
+                return packageNames;
+            }
+        }).flatMap(List::stream).sorted().distinct().collect(Collectors.toList());
+
+        return neededPackages;
+    }
+
+    private static List<Path> getNeededLibsForFile(Path path) throws IOException {
+        List<Path> result = new ArrayList<>();
+        int ret = Executor.of(TOOL_LDD, path.toString()).setOutputConsumer(lines -> {
+            lines.map(line -> {
+                Matcher matcher = LIB_IN_LDD_OUTPUT_REGEX.matcher(line);
+                if (matcher.find()) {
+                    return matcher.group(1);
+                }
+                return null;
+            }).filter(Objects::nonNull).map(Path::of).forEach(result::add);
+        }).execute();
+
+        if (ret != 0) {
+            // objdump failed. This is OK if the tool was applied to not a binary file
+            return Collections.emptyList();
+        }
+
+        return result;
+    }
+
+    private static Collection<Path> getNeededLibsForFiles(List<Path> paths) {
+        // Depending on tool used, the set can contain full paths (ldd) or
+        // only file names (objdump).
+        Set<Path> allLibs = paths.stream().map(path -> {
+            List<Path> libs;
+            try {
+                libs = getNeededLibsForFile(path);
+            } catch (IOException ex) {
+                Log.verbose(ex);
+                libs = Collections.emptyList();
+            }
+            return libs;
+        }).flatMap(List::stream).collect(Collectors.toSet());
+
+        // `allLibs` contains names of all .so needed by files from `paths` list.
+        // If there are mutual dependencies between binaries from `paths` list,
+        // then names or full paths to these binaries are in `allLibs` set.
+        // Remove these items from `allLibs`.
+        Set<Path> excludedNames = paths.stream().map(Path::getFileName).collect(
+                Collectors.toSet());
+        Iterator<Path> it = allLibs.iterator();
+        while (it.hasNext()) {
+            Path libName = it.next().getFileName();
+            if (excludedNames.contains(libName)) {
+                it.remove();
+            }
+        }
+
+        return allLibs;
+    }
+
+    private static boolean canDependOnLibs(Path path) {
+        return path.toFile().canExecute() || path.toString().endsWith(".so");
+    }
+
+    @FunctionalInterface
+    public interface PackageLookup {
+        Stream<String> apply(Path path) throws IOException;
+    }
+
+    private PackageLookup packageLookup;
+
+    private static final String TOOL_LDD = "ldd";
+
+    //
+    // Typical ldd output:
+    //
+    // ldd: warning: you do not have execution permission for `/tmp/jdk.incubator.jpackage17911687595930080396/images/opt/simplepackagetest/lib/runtime/lib/libawt_headless.so'
+    //  linux-vdso.so.1 =>  (0x00007ffce6bfd000)
+    //  libawt.so => /tmp/jdk.incubator.jpackage17911687595930080396/images/opt/simplepackagetest/lib/runtime/lib/libawt.so (0x00007f4e00c75000)
+    //  libjvm.so => not found
+    //  libjava.so => /tmp/jdk.incubator.jpackage17911687595930080396/images/opt/simplepackagetest/lib/runtime/lib/libjava.so (0x00007f4e00c41000)
+    //  libm.so.6 => /lib64/libm.so.6 (0x00007f4e00834000)
+    //  libdl.so.2 => /lib64/libdl.so.2 (0x00007f4e00630000)
+    //  libc.so.6 => /lib64/libc.so.6 (0x00007f4e00262000)
+    //  libjvm.so => not found
+    //  libjvm.so => not found
+    //  libverify.so => /tmp/jdk.incubator.jpackage17911687595930080396/images/opt/simplepackagetest/lib/runtime/lib/libverify.so (0x00007f4e00c2e000)
+    //  /lib64/ld-linux-x86-64.so.2 (0x00007f4e00b36000)
+    //  libjvm.so => not found
+    //
+    private static final Pattern LIB_IN_LDD_OUTPUT_REGEX = Pattern.compile(
+            "^\\s*\\S+\\s*=>\\s*(\\S+)\\s+\\(0[xX]\\p{XDigit}+\\)");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.*;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+public class LinuxAppBundler extends AbstractImageBundler {
+
+    static final BundlerParamInfo<File> ICON_PNG =
+            new StandardBundlerParam<>(
+            "icon.png",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".png")) {
+                    Log.error(MessageFormat.format(
+                            I18N.getString("message.icon-not-png"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+    static final BundlerParamInfo<String> LINUX_INSTALL_DIR =
+            new StandardBundlerParam<>(
+            "linux-install-dir",
+            String.class,
+            params -> {
+                 String dir = INSTALL_DIR.fetchFrom(params);
+                 if (dir != null) {
+                     if (dir.endsWith("/")) {
+                         dir = dir.substring(0, dir.length()-1);
+                     }
+                     return dir;
+                 }
+                 return "/opt";
+             },
+            (s, p) -> s
+    );
+
+    static final BundlerParamInfo<String> LINUX_PACKAGE_DEPENDENCIES =
+            new StandardBundlerParam<>(
+            Arguments.CLIOptions.LINUX_PACKAGE_DEPENDENCIES.getId(),
+            String.class,
+            params -> {
+                 return "";
+             },
+            (s, p) -> s
+    );
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws ConfigException {
+        try {
+            Objects.requireNonNull(params);
+            return doValidate(params);
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    private boolean doValidate(Map<String, ? super Object> params)
+            throws ConfigException {
+
+        imageBundleValidation(params);
+
+        return true;
+    }
+
+    File doBundle(Map<String, ? super Object> params, File outputDirectory,
+            boolean dependentTask) throws PackagerException {
+        if (StandardBundlerParam.isRuntimeInstaller(params)) {
+            return PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
+        } else {
+            return doAppBundle(params, outputDirectory, dependentTask);
+        }
+    }
+
+    private File doAppBundle(Map<String, ? super Object> params,
+            File outputDirectory, boolean dependentTask)
+            throws PackagerException {
+        try {
+            File rootDirectory = createRoot(params, outputDirectory,
+                    dependentTask, APP_NAME.fetchFrom(params));
+            AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder(
+                    params, outputDirectory.toPath());
+            if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(params) == null ) {
+                JLinkBundlerHelper.execute(params, appBuilder);
+            } else {
+                StandardBundlerParam.copyPredefinedRuntimeImage(
+                        params, appBuilder);
+            }
+            return rootDirectory;
+        } catch (PackagerException pe) {
+            throw pe;
+        } catch (Exception ex) {
+            Log.verbose(ex);
+            throw new PackagerException(ex);
+        }
+    }
+
+    @Override
+    public String getName() {
+        return I18N.getString("app.bundler.name");
+    }
+
+    @Override
+    public String getID() {
+        return "linux.app";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "IMAGE";
+    }
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) throws PackagerException {
+        return doBundle(params, outputParentDir, false);
+    }
+
+    @Override
+    public boolean supported(boolean runtimeInstaller) {
+        return true;
+    }
+
+    @Override
+    public boolean isDefault() {
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppImageBuilder.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2015, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
+
+    private static final String LIBRARY_NAME = "libapplauncher.so";
+    final static String DEFAULT_ICON = "java32.png";
+
+    private final ApplicationLayout appLayout;
+
+    public static final BundlerParamInfo<File> ICON_PNG =
+            new StandardBundlerParam<>(
+            "icon.png",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".png")) {
+                    Log.error(MessageFormat.format(I18N.getString(
+                            "message.icon-not-png"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+    private static ApplicationLayout createAppLayout(Map<String, Object> params,
+            Path imageOutDir) {
+        return ApplicationLayout.linuxAppImage().resolveAt(
+                imageOutDir.resolve(APP_NAME.fetchFrom(params)));
+    }
+
+    public LinuxAppImageBuilder(Map<String, Object> params, Path imageOutDir)
+            throws IOException {
+        super(params, createAppLayout(params, imageOutDir).runtimeDirectory());
+
+        appLayout = createAppLayout(params, imageOutDir);
+    }
+
+    private void writeEntry(InputStream in, Path dstFile) throws IOException {
+        Files.createDirectories(dstFile.getParent());
+        Files.copy(in, dstFile);
+    }
+
+    public static String getLauncherName(Map<String, ? super Object> params) {
+        return APP_NAME.fetchFrom(params);
+    }
+
+    private Path getLauncherCfgPath(Map<String, ? super Object> params) {
+        return appLayout.appDirectory().resolve(
+                APP_NAME.fetchFrom(params) + ".cfg");
+    }
+
+    @Override
+    public Path getAppDir() {
+        return appLayout.appDirectory();
+    }
+
+    @Override
+    public Path getAppModsDir() {
+        return appLayout.appModsDirectory();
+    }
+
+    @Override
+    protected String getCfgAppDir() {
+        return Path.of("$ROOTDIR").resolve(
+                ApplicationLayout.linuxAppImage().appDirectory()).toString()
+                + File.separator;
+    }
+
+    @Override
+    protected String getCfgRuntimeDir() {
+        return Path.of("$ROOTDIR").resolve(
+              ApplicationLayout.linuxAppImage().runtimeDirectory()).toString();
+    }
+
+    @Override
+    public void prepareApplicationFiles(Map<String, ? super Object> params)
+            throws IOException {
+        Map<String, ? super Object> originalParams = new HashMap<>(params);
+
+        appLayout.roots().stream().forEach(dir -> {
+            try {
+                IOUtils.writableOutputDir(dir);
+            } catch (PackagerException pe) {
+                throw new RuntimeException(pe);
+            }
+        });
+
+        // create the primary launcher
+        createLauncherForEntryPoint(params);
+
+        // Copy library to the launcher folder
+        try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
+            writeEntry(is_lib, appLayout.dllDirectory().resolve(LIBRARY_NAME));
+        }
+
+        // create the additional launchers, if any
+        List<Map<String, ? super Object>> entryPoints
+                = StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
+        for (Map<String, ? super Object> entryPoint : entryPoints) {
+            createLauncherForEntryPoint(
+                    AddLauncherArguments.merge(originalParams, entryPoint));
+        }
+
+        // Copy class path entries to Java folder
+        copyApplication(params);
+
+        // Copy icon to Resources folder
+        copyIcon(params);
+    }
+
+    @Override
+    public void prepareJreFiles(Map<String, ? super Object> params)
+            throws IOException {}
+
+    private void createLauncherForEntryPoint(
+            Map<String, ? super Object> params) throws IOException {
+        // Copy executable to launchers folder
+        Path executableFile = appLayout.launchersDirectory().resolve(getLauncherName(params));
+        try (InputStream is_launcher =
+                getResourceAsStream("jpackageapplauncher")) {
+            writeEntry(is_launcher, executableFile);
+        }
+
+        executableFile.toFile().setExecutable(true, false);
+        executableFile.toFile().setWritable(true, true);
+
+        writeCfgFile(params, getLauncherCfgPath(params).toFile());
+    }
+
+    private void copyIcon(Map<String, ? super Object> params)
+            throws IOException {
+
+        Path iconTarget = appLayout.destktopIntegrationDirectory().resolve(
+                APP_NAME.fetchFrom(params) + IOUtils.getSuffix(Path.of(
+                DEFAULT_ICON)));
+
+        createResource(DEFAULT_ICON, params)
+                .setCategory("icon")
+                .setExternal(ICON_PNG.fetchFrom(params))
+                .saveToFile(iconTarget);
+    }
+
+    private void copyApplication(Map<String, ? super Object> params)
+            throws IOException {
+        for (RelativeFileSet appResources :
+                APP_RESOURCES_LIST.fetchFrom(params)) {
+            if (appResources == null) {
+                throw new RuntimeException("Null app resources?");
+            }
+            File srcdir = appResources.getBaseDirectory();
+            for (String fname : appResources.getIncludedFiles()) {
+                copyEntry(appLayout.appDirectory(), srcdir, fname);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxDebBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.*;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import static jdk.incubator.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+
+public class LinuxDebBundler extends LinuxPackageBundler {
+
+    // Debian rules for package naming are used here
+    // https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
+    //
+    // Package names must consist only of lower case letters (a-z),
+    // digits (0-9), plus (+) and minus (-) signs, and periods (.).
+    // They must be at least two characters long and
+    // must start with an alphanumeric character.
+    //
+    private static final Pattern DEB_PACKAGE_NAME_PATTERN =
+            Pattern.compile("^[a-z][a-z\\d\\+\\-\\.]+");
+
+    private static final BundlerParamInfo<String> PACKAGE_NAME =
+            new StandardBundlerParam<> (
+            Arguments.CLIOptions.LINUX_BUNDLE_NAME.getId(),
+            String.class,
+            params -> {
+                String nm = APP_NAME.fetchFrom(params);
+
+                if (nm == null) return null;
+
+                // make sure to lower case and spaces/underscores become dashes
+                nm = nm.toLowerCase().replaceAll("[ _]", "-");
+                return nm;
+            },
+            (s, p) -> {
+                if (!DEB_PACKAGE_NAME_PATTERN.matcher(s).matches()) {
+                    throw new IllegalArgumentException(new ConfigException(
+                            MessageFormat.format(I18N.getString(
+                            "error.invalid-value-for-package-name"), s),
+                            I18N.getString(
+                            "error.invalid-value-for-package-name.advice")));
+                }
+
+                return s;
+            });
+
+    private final static String TOOL_DPKG_DEB = "dpkg-deb";
+    private final static String TOOL_DPKG = "dpkg";
+    private final static String TOOL_FAKEROOT = "fakeroot";
+
+    private final static String DEB_ARCH;
+    static {
+        String debArch;
+        try {
+            debArch = Executor.of(TOOL_DPKG, "--print-architecture").saveOutput(
+                    true).executeExpectSuccess().getOutput().get(0);
+        } catch (IOException ex) {
+            debArch = null;
+        }
+        DEB_ARCH = debArch;
+    }
+
+    private static final BundlerParamInfo<String> FULL_PACKAGE_NAME =
+            new StandardBundlerParam<>(
+                    "linux.deb.fullPackageName", String.class, params -> {
+                        return PACKAGE_NAME.fetchFrom(params)
+                            + "_" + VERSION.fetchFrom(params)
+                            + "-" + RELEASE.fetchFrom(params)
+                            + "_" + DEB_ARCH;
+                    }, (s, p) -> s);
+
+    private static final BundlerParamInfo<String> EMAIL =
+            new StandardBundlerParam<> (
+            Arguments.CLIOptions.LINUX_DEB_MAINTAINER.getId(),
+            String.class,
+            params -> "Unknown",
+            (s, p) -> s);
+
+    private static final BundlerParamInfo<String> MAINTAINER =
+            new StandardBundlerParam<> (
+            BundleParams.PARAM_MAINTAINER,
+            String.class,
+            params -> VENDOR.fetchFrom(params) + " <"
+                    + EMAIL.fetchFrom(params) + ">",
+            (s, p) -> s);
+
+    private static final BundlerParamInfo<String> SECTION =
+            new StandardBundlerParam<>(
+            Arguments.CLIOptions.LINUX_CATEGORY.getId(),
+            String.class,
+            params -> "misc",
+            (s, p) -> s);
+
+    private static final BundlerParamInfo<String> LICENSE_TEXT =
+            new StandardBundlerParam<> (
+            "linux.deb.licenseText",
+            String.class,
+            params -> {
+                try {
+                    String licenseFile = LICENSE_FILE.fetchFrom(params);
+                    if (licenseFile != null) {
+                        return Files.readString(Path.of(licenseFile));
+                    }
+                } catch (IOException e) {
+                    Log.verbose(e);
+                }
+                return "Unknown";
+            },
+            (s, p) -> s);
+
+    public LinuxDebBundler() {
+        super(PACKAGE_NAME);
+    }
+
+    @Override
+    public void doValidate(Map<String, ? super Object> params)
+            throws ConfigException {
+
+        // Show warning if license file is missing
+        if (LICENSE_FILE.fetchFrom(params) == null) {
+            Log.verbose(I18N.getString("message.debs-like-licenses"));
+        }
+    }
+
+    @Override
+    protected List<ToolValidator> getToolValidators(
+            Map<String, ? super Object> params) {
+        return Stream.of(TOOL_DPKG_DEB, TOOL_DPKG, TOOL_FAKEROOT).map(
+                ToolValidator::new).collect(Collectors.toList());
+    }
+
+    @Override
+    protected File buildPackageBundle(
+            Map<String, String> replacementData,
+            Map<String, ? super Object> params, File outputParentDir) throws
+            PackagerException, IOException {
+
+        prepareProjectConfig(replacementData, params);
+        adjustPermissionsRecursive(createMetaPackage(params).sourceRoot().toFile());
+        return buildDeb(params, outputParentDir);
+    }
+
+    private static final Pattern PACKAGE_NAME_REGEX = Pattern.compile("^(^\\S+):");
+
+    @Override
+    protected void initLibProvidersLookup(
+            Map<String, ? super Object> params,
+            LibProvidersLookup libProvidersLookup) {
+
+        //
+        // `dpkg -S` command does glob pattern lookup. If not the absolute path
+        // to the file is specified it might return mltiple package names.
+        // Even for full paths multiple package names can be returned as
+        // it is OK for multiple packages to provide the same file. `/opt`
+        // directory is such an example. So we have to deal with multiple
+        // packages per file situation.
+        //
+        // E.g.: `dpkg -S libc.so.6` command reports three packages:
+        // libc6-x32: /libx32/libc.so.6
+        // libc6:amd64: /lib/x86_64-linux-gnu/libc.so.6
+        // libc6-i386: /lib32/libc.so.6
+        // `:amd64` is architecture suffix and can (should) be dropped.
+        // Still need to decide what package to choose from three.
+        // libc6-x32 and libc6-i386 both depend on libc6:
+        // $ dpkg -s libc6-x32
+        // Package: libc6-x32
+        // Status: install ok installed
+        // Priority: optional
+        // Section: libs
+        // Installed-Size: 10840
+        // Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+        // Architecture: amd64
+        // Source: glibc
+        // Version: 2.23-0ubuntu10
+        // Depends: libc6 (= 2.23-0ubuntu10)
+        //
+        // We can dive into tracking dependencies, but this would be overly
+        // complicated.
+        //
+        // For simplicity lets consider the following rules:
+        // 1. If there is one item in `dpkg -S` output, accept it.
+        // 2. If there are multiple items in `dpkg -S` output and there is at
+        //  least one item with the default arch suffix (DEB_ARCH),
+        //  accept only these items.
+        // 3. If there are multiple items in `dpkg -S` output and there are
+        //  no with the default arch suffix (DEB_ARCH), accept all items.
+        // So lets use this heuristics: don't accept packages for whom
+        //  `dpkg -p` command fails.
+        // 4. Arch suffix should be stripped from accepted package names.
+        //
+
+        libProvidersLookup.setPackageLookup(file -> {
+            Set<String> archPackages = new HashSet<>();
+            Set<String> otherPackages = new HashSet<>();
+
+            Executor.of(TOOL_DPKG, "-S", file.toString())
+                    .saveOutput(true).executeExpectSuccess()
+                    .getOutput().forEach(line -> {
+                        Matcher matcher = PACKAGE_NAME_REGEX.matcher(line);
+                        if (matcher.find()) {
+                            String name = matcher.group(1);
+                            if (name.endsWith(":" + DEB_ARCH)) {
+                                // Strip arch suffix
+                                name = name.substring(0,
+                                        name.length() - (DEB_ARCH.length() + 1));
+                                archPackages.add(name);
+                            } else {
+                                otherPackages.add(name);
+                            }
+                        }
+                    });
+
+            if (!archPackages.isEmpty()) {
+                return archPackages.stream();
+            }
+            return otherPackages.stream();
+        });
+    }
+
+    @Override
+    protected List<ConfigException> verifyOutputBundle(
+            Map<String, ? super Object> params, Path packageBundle) {
+        List<ConfigException> errors = new ArrayList<>();
+
+        String controlFileName = "control";
+
+        List<PackageProperty> properties = List.of(
+                new PackageProperty("Package", PACKAGE_NAME.fetchFrom(params),
+                        "APPLICATION_PACKAGE", controlFileName),
+                new PackageProperty("Version", String.format("%s-%s",
+                        VERSION.fetchFrom(params), RELEASE.fetchFrom(params)),
+                        "APPLICATION_VERSION-APPLICATION_RELEASE",
+                        controlFileName),
+                new PackageProperty("Architecture", DEB_ARCH, "APPLICATION_ARCH",
+                        controlFileName));
+
+        List<String> cmdline = new ArrayList<>(List.of(TOOL_DPKG_DEB, "-f",
+                packageBundle.toString()));
+        properties.forEach(property -> cmdline.add(property.name));
+        try {
+            Map<String, String> actualValues = Executor.of(cmdline.toArray(String[]::new))
+                    .saveOutput(true)
+                    .executeExpectSuccess()
+                    .getOutput().stream()
+                            .map(line -> line.split(":\\s+", 2))
+                            .collect(Collectors.toMap(
+                                    components -> components[0],
+                                    components -> components[1]));
+            properties.forEach(property -> errors.add(property.verifyValue(
+                    actualValues.get(property.name))));
+        } catch (IOException ex) {
+            // Ignore error as it is not critical. Just report it.
+            Log.verbose(ex);
+        }
+
+        return errors;
+    }
+
+    /*
+     * set permissions with a string like "rwxr-xr-x"
+     *
+     * This cannot be directly backport to 22u which is built with 1.6
+     */
+    private void setPermissions(File file, String permissions) {
+        Set<PosixFilePermission> filePermissions =
+                PosixFilePermissions.fromString(permissions);
+        try {
+            if (file.exists()) {
+                Files.setPosixFilePermissions(file.toPath(), filePermissions);
+            }
+        } catch (IOException ex) {
+            Log.error(ex.getMessage());
+            Log.verbose(ex);
+        }
+
+    }
+
+    public static boolean isDebian() {
+        // we are just going to run "dpkg -s coreutils" and assume Debian
+        // or deritive if no error is returned.
+        try {
+            Executor.of(TOOL_DPKG, "-s", "coreutils").executeExpectSuccess();
+            return true;
+        } catch (IOException e) {
+            // just fall thru
+        }
+        return false;
+    }
+
+    private void adjustPermissionsRecursive(File dir) throws IOException {
+        Files.walkFileTree(dir.toPath(), new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file,
+                    BasicFileAttributes attrs)
+                    throws IOException {
+                if (file.endsWith(".so") || !Files.isExecutable(file)) {
+                    setPermissions(file.toFile(), "rw-r--r--");
+                } else if (Files.isExecutable(file)) {
+                    setPermissions(file.toFile(), "rwxr-xr-x");
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir, IOException e)
+                    throws IOException {
+                if (e == null) {
+                    setPermissions(dir.toFile(), "rwxr-xr-x");
+                    return FileVisitResult.CONTINUE;
+                } else {
+                    // directory iteration failed
+                    throw e;
+                }
+            }
+        });
+    }
+
+    private class DebianFile {
+
+        DebianFile(Path dstFilePath, String comment) {
+            this.dstFilePath = dstFilePath;
+            this.comment = comment;
+        }
+
+        DebianFile setExecutable() {
+            permissions = "rwxr-xr-x";
+            return this;
+        }
+
+        void create(Map<String, String> data, Map<String, ? super Object> params)
+                throws IOException {
+            createResource("template." + dstFilePath.getFileName().toString(),
+                    params)
+                    .setCategory(I18N.getString(comment))
+                    .setSubstitutionData(data)
+                    .saveToFile(dstFilePath);
+            if (permissions != null) {
+                setPermissions(dstFilePath.toFile(), permissions);
+            }
+        }
+
+        private final Path dstFilePath;
+        private final String comment;
+        private String permissions;
+    }
+
+    private void prepareProjectConfig(Map<String, String> data,
+            Map<String, ? super Object> params) throws IOException {
+
+        Path configDir = createMetaPackage(params).sourceRoot().resolve("DEBIAN");
+        List<DebianFile> debianFiles = new ArrayList<>();
+        debianFiles.add(new DebianFile(
+                configDir.resolve("control"),
+                "resource.deb-control-file"));
+        debianFiles.add(new DebianFile(
+                configDir.resolve("preinst"),
+                "resource.deb-preinstall-script").setExecutable());
+        debianFiles.add(new DebianFile(
+                configDir.resolve("prerm"),
+                "resource.deb-prerm-script").setExecutable());
+        debianFiles.add(new DebianFile(
+                configDir.resolve("postinst"),
+                "resource.deb-postinstall-script").setExecutable());
+        debianFiles.add(new DebianFile(
+                configDir.resolve("postrm"),
+                "resource.deb-postrm-script").setExecutable());
+
+        if (!StandardBundlerParam.isRuntimeInstaller(params)) {
+            debianFiles.add(new DebianFile(
+                    getConfig_CopyrightFile(params).toPath(),
+                    "resource.copyright-file"));
+        }
+
+        for (DebianFile debianFile : debianFiles) {
+            debianFile.create(data, params);
+        }
+    }
+
+    @Override
+    protected Map<String, String> createReplacementData(
+            Map<String, ? super Object> params) throws IOException {
+        Map<String, String> data = new HashMap<>();
+
+        data.put("APPLICATION_MAINTAINER", MAINTAINER.fetchFrom(params));
+        data.put("APPLICATION_SECTION", SECTION.fetchFrom(params));
+        data.put("APPLICATION_COPYRIGHT", COPYRIGHT.fetchFrom(params));
+        data.put("APPLICATION_LICENSE_TEXT", LICENSE_TEXT.fetchFrom(params));
+        data.put("APPLICATION_ARCH", DEB_ARCH);
+        data.put("APPLICATION_INSTALLED_SIZE", Long.toString(
+                createMetaPackage(params).sourceApplicationLayout().sizeInBytes() >> 10));
+
+        return data;
+    }
+
+    private File getConfig_CopyrightFile(Map<String, ? super Object> params) {
+        PlatformPackage thePackage = createMetaPackage(params);
+        return thePackage.sourceRoot().resolve(Path.of(".",
+                LINUX_INSTALL_DIR.fetchFrom(params), PACKAGE_NAME.fetchFrom(
+                params), "share/doc/copyright")).toFile();
+    }
+
+    private File buildDeb(Map<String, ? super Object> params,
+            File outdir) throws IOException {
+        File outFile = new File(outdir,
+                FULL_PACKAGE_NAME.fetchFrom(params)+".deb");
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.outputting-to-location"), outFile.getAbsolutePath()));
+
+        PlatformPackage thePackage = createMetaPackage(params);
+
+        List<String> cmdline = new ArrayList<>();
+        cmdline.addAll(List.of(TOOL_FAKEROOT, TOOL_DPKG_DEB));
+        if (Log.isVerbose()) {
+            cmdline.add("--verbose");
+        }
+        cmdline.addAll(List.of("-b", thePackage.sourceRoot().toString(),
+                outFile.getAbsolutePath()));
+
+        // run dpkg
+        Executor.of(cmdline.toArray(String[]::new)).executeExpectSuccess();
+
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.output-to-location"), outFile.getAbsolutePath()));
+
+        return outFile;
+    }
+
+    @Override
+    public String getName() {
+        return I18N.getString("deb.bundler.name");
+    }
+
+    @Override
+    public String getID() {
+        return "deb";
+    }
+
+    @Override
+    public boolean supported(boolean runtimeInstaller) {
+        return Platform.isLinux() && (new ToolValidator(TOOL_DPKG_DEB).validate() == null);
+    }
+
+    @Override
+    public boolean isDefault() {
+        return isDebian();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.*;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import static jdk.incubator.jpackage.internal.DesktopIntegration.*;
+import static jdk.incubator.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
+import static jdk.incubator.jpackage.internal.LinuxAppBundler.LINUX_PACKAGE_DEPENDENCIES;
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+
+abstract class LinuxPackageBundler extends AbstractBundler {
+
+    LinuxPackageBundler(BundlerParamInfo<String> packageName) {
+        this.packageName = packageName;
+    }
+
+    @Override
+    final public boolean validate(Map<String, ? super Object> params)
+            throws ConfigException {
+
+        // run basic validation to ensure requirements are met
+        // we are not interested in return code, only possible exception
+        APP_BUNDLER.fetchFrom(params).validate(params);
+
+        validateInstallDir(LINUX_INSTALL_DIR.fetchFrom(params));
+
+        validateFileAssociations(FILE_ASSOCIATIONS.fetchFrom(params));
+
+        // If package name has some restrictions, the string converter will
+        // throw an exception if invalid
+        packageName.getStringConverter().apply(packageName.fetchFrom(params),
+            params);
+
+        for (var validator: getToolValidators(params)) {
+            ConfigException ex = validator.validate();
+            if (ex != null) {
+                throw ex;
+            }
+        }
+
+        withFindNeededPackages = LibProvidersLookup.supported();
+        if (!withFindNeededPackages) {
+            final String advice;
+            if ("deb".equals(getID())) {
+                advice = "message.deb-ldd-not-available.advice";
+            } else {
+                advice = "message.rpm-ldd-not-available.advice";
+            }
+            // Let user know package dependencies will not be generated.
+            Log.error(String.format("%s\n%s", I18N.getString(
+                    "message.ldd-not-available"), I18N.getString(advice)));
+        }
+
+        // Packaging specific validation
+        doValidate(params);
+
+        return true;
+    }
+
+    @Override
+    final public String getBundleType() {
+        return "INSTALLER";
+    }
+
+    @Override
+    final public File execute(Map<String, ? super Object> params,
+            File outputParentDir) throws PackagerException {
+        IOUtils.writableOutputDir(outputParentDir.toPath());
+
+        PlatformPackage thePackage = createMetaPackage(params);
+
+        Function<File, ApplicationLayout> initAppImageLayout = imageRoot -> {
+            ApplicationLayout layout = appImageLayout(params);
+            layout.pathGroup().setPath(new Object(),
+                    AppImageFile.getPathInAppImage(Path.of("")));
+            return layout.resolveAt(imageRoot.toPath());
+        };
+
+        try {
+            File appImage = StandardBundlerParam.getPredefinedAppImage(params);
+
+            // we either have an application image or need to build one
+            if (appImage != null) {
+                initAppImageLayout.apply(appImage).copy(
+                        thePackage.sourceApplicationLayout());
+            } else {
+                appImage = APP_BUNDLER.fetchFrom(params).doBundle(params,
+                        thePackage.sourceRoot().toFile(), true);
+                ApplicationLayout srcAppLayout = initAppImageLayout.apply(
+                        appImage);
+                if (appImage.equals(PREDEFINED_RUNTIME_IMAGE.fetchFrom(params))) {
+                    // Application image points to run-time image.
+                    // Copy it.
+                    srcAppLayout.copy(thePackage.sourceApplicationLayout());
+                } else {
+                    // Application image is a newly created directory tree.
+                    // Move it.
+                    srcAppLayout.move(thePackage.sourceApplicationLayout());
+                    if (appImage.exists()) {
+                        // Empty app image directory might remain after all application
+                        // directories have been moved.
+                        appImage.delete();
+                    }
+                }
+            }
+
+            if (!StandardBundlerParam.isRuntimeInstaller(params)) {
+                desktopIntegration = new DesktopIntegration(thePackage, params);
+            } else {
+                desktopIntegration = null;
+            }
+
+            Map<String, String> data = createDefaultReplacementData(params);
+            if (desktopIntegration != null) {
+                data.putAll(desktopIntegration.create());
+            } else {
+                Stream.of(DESKTOP_COMMANDS_INSTALL, DESKTOP_COMMANDS_UNINSTALL,
+                        UTILITY_SCRIPTS).forEach(v -> data.put(v, ""));
+            }
+
+            data.putAll(createReplacementData(params));
+
+            File packageBundle = buildPackageBundle(Collections.unmodifiableMap(
+                    data), params, outputParentDir);
+
+            verifyOutputBundle(params, packageBundle.toPath()).stream()
+                    .filter(Objects::nonNull)
+                    .forEachOrdered(ex -> {
+                Log.verbose(ex.getLocalizedMessage());
+                Log.verbose(ex.getAdvice());
+            });
+
+            return packageBundle;
+        } catch (IOException ex) {
+            Log.verbose(ex);
+            throw new PackagerException(ex);
+        }
+    }
+
+    private List<String> getListOfNeededPackages(
+            Map<String, ? super Object> params) throws IOException {
+
+        PlatformPackage thePackage = createMetaPackage(params);
+
+        final List<String> xdgUtilsPackage;
+        if (desktopIntegration != null) {
+            xdgUtilsPackage = desktopIntegration.requiredPackages();
+        } else {
+            xdgUtilsPackage = Collections.emptyList();
+        }
+
+        final List<String> neededLibPackages;
+        if (withFindNeededPackages) {
+            LibProvidersLookup lookup = new LibProvidersLookup();
+            initLibProvidersLookup(params, lookup);
+
+            neededLibPackages = lookup.execute(thePackage.sourceRoot());
+        } else {
+            neededLibPackages = Collections.emptyList();
+        }
+
+        // Merge all package lists together.
+        // Filter out empty names, sort and remove duplicates.
+        List<String> result = Stream.of(xdgUtilsPackage, neededLibPackages).flatMap(
+                List::stream).filter(Predicate.not(String::isEmpty)).sorted().distinct().collect(
+                Collectors.toList());
+
+        Log.verbose(String.format("Required packages: %s", result));
+
+        return result;
+    }
+
+    private Map<String, String> createDefaultReplacementData(
+            Map<String, ? super Object> params) throws IOException {
+        Map<String, String> data = new HashMap<>();
+
+        data.put("APPLICATION_PACKAGE", createMetaPackage(params).name());
+        data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
+        data.put("APPLICATION_VERSION", VERSION.fetchFrom(params));
+        data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
+        data.put("APPLICATION_RELEASE", RELEASE.fetchFrom(params));
+
+        String defaultDeps = String.join(", ", getListOfNeededPackages(params));
+        String customDeps = LINUX_PACKAGE_DEPENDENCIES.fetchFrom(params).strip();
+        if (!customDeps.isEmpty() && !defaultDeps.isEmpty()) {
+            customDeps = ", " + customDeps;
+        }
+        data.put("PACKAGE_DEFAULT_DEPENDENCIES", defaultDeps);
+        data.put("PACKAGE_CUSTOM_DEPENDENCIES", customDeps);
+
+        return data;
+    }
+
+    abstract protected List<ConfigException> verifyOutputBundle(
+            Map<String, ? super Object> params, Path packageBundle);
+
+    abstract protected void initLibProvidersLookup(
+            Map<String, ? super Object> params,
+            LibProvidersLookup libProvidersLookup);
+
+    abstract protected List<ToolValidator> getToolValidators(
+            Map<String, ? super Object> params);
+
+    abstract protected void doValidate(Map<String, ? super Object> params)
+            throws ConfigException;
+
+    abstract protected Map<String, String> createReplacementData(
+            Map<String, ? super Object> params) throws IOException;
+
+    abstract protected File buildPackageBundle(
+            Map<String, String> replacementData,
+            Map<String, ? super Object> params, File outputParentDir) throws
+            PackagerException, IOException;
+
+    final protected PlatformPackage createMetaPackage(
+            Map<String, ? super Object> params) {
+        return new PlatformPackage() {
+            @Override
+            public String name() {
+                return packageName.fetchFrom(params);
+            }
+
+            @Override
+            public Path sourceRoot() {
+                return IMAGES_ROOT.fetchFrom(params).toPath().toAbsolutePath();
+            }
+
+            @Override
+            public ApplicationLayout sourceApplicationLayout() {
+                return appImageLayout(params).resolveAt(
+                        applicationInstallDir(sourceRoot()));
+            }
+
+            @Override
+            public ApplicationLayout installedApplicationLayout() {
+                return appImageLayout(params).resolveAt(
+                        applicationInstallDir(Path.of("/")));
+            }
+
+            private Path applicationInstallDir(Path root) {
+                Path installDir = Path.of(LINUX_INSTALL_DIR.fetchFrom(params),
+                        name());
+                if (installDir.isAbsolute()) {
+                    installDir = Path.of("." + installDir.toString()).normalize();
+                }
+                return root.resolve(installDir);
+            }
+        };
+    }
+
+    private ApplicationLayout appImageLayout(
+            Map<String, ? super Object> params) {
+        if (StandardBundlerParam.isRuntimeInstaller(params)) {
+            return ApplicationLayout.javaRuntime();
+        }
+        return ApplicationLayout.linuxAppImage();
+    }
+
+    private static void validateInstallDir(String installDir) throws
+            ConfigException {
+        if (installDir.startsWith("/usr/") || installDir.equals("/usr")) {
+            throw new ConfigException(MessageFormat.format(I18N.getString(
+                    "error.unsupported-install-dir"), installDir), null);
+        }
+
+        if (installDir.isEmpty()) {
+            throw new ConfigException(MessageFormat.format(I18N.getString(
+                    "error.invalid-install-dir"), "/"), null);
+        }
+
+        boolean valid = false;
+        try {
+            final Path installDirPath = Path.of(installDir);
+            valid = installDirPath.isAbsolute();
+            if (valid && !installDirPath.normalize().toString().equals(
+                    installDirPath.toString())) {
+                // Don't allow '/opt/foo/..' or /opt/.
+                valid = false;
+            }
+        } catch (InvalidPathException ex) {
+        }
+
+        if (!valid) {
+            throw new ConfigException(MessageFormat.format(I18N.getString(
+                    "error.invalid-install-dir"), installDir), null);
+        }
+    }
+
+    private static void validateFileAssociations(
+            List<Map<String, ? super Object>> associations) throws
+            ConfigException {
+        // only one mime type per association, at least one file extention
+        int assocIdx = 0;
+        for (var assoc : associations) {
+            ++assocIdx;
+            List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc);
+            if (mimes == null || mimes.isEmpty()) {
+                String msgKey = "error.no-content-types-for-file-association";
+                throw new ConfigException(
+                        MessageFormat.format(I18N.getString(msgKey), assocIdx),
+                        I18N.getString(msgKey + ".advise"));
+
+            }
+
+            if (mimes.size() > 1) {
+                String msgKey = "error.too-many-content-types-for-file-association";
+                throw new ConfigException(
+                        MessageFormat.format(I18N.getString(msgKey), assocIdx),
+                        I18N.getString(msgKey + ".advise"));
+            }
+        }
+    }
+
+    private final BundlerParamInfo<String> packageName;
+    private boolean withFindNeededPackages;
+    private DesktopIntegration desktopIntegration;
+
+    private static final BundlerParamInfo<LinuxAppBundler> APP_BUNDLER =
+        new StandardBundlerParam<>(
+                "linux.app.bundler",
+                LinuxAppBundler.class,
+                (params) -> new LinuxAppBundler(),
+                null
+        );
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxRpmBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.*;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+import static jdk.incubator.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+
+/**
+ * There are two command line options to configure license information for RPM
+ * packaging: --linux-rpm-license-type and --license-file. Value of
+ * --linux-rpm-license-type command line option configures "License:" section
+ * of RPM spec. Value of --license-file command line option specifies a license
+ * file to be added to the package. License file is a sort of documentation file
+ * but it will be installed even if user selects an option to install the
+ * package without documentation. --linux-rpm-license-type is the primary option
+ * to set license information. --license-file makes little sense in case of RPM
+ * packaging.
+ */
+public class LinuxRpmBundler extends LinuxPackageBundler {
+
+    // Fedora rules for package naming are used here
+    // https://fedoraproject.org/wiki/Packaging:NamingGuidelines?rd=Packaging/NamingGuidelines
+    //
+    // all Fedora packages must be named using only the following ASCII
+    // characters. These characters are displayed here:
+    //
+    // abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._+
+    //
+    private static final Pattern RPM_PACKAGE_NAME_PATTERN =
+            Pattern.compile("[a-z\\d\\+\\-\\.\\_]+", Pattern.CASE_INSENSITIVE);
+
+    public static final BundlerParamInfo<String> PACKAGE_NAME =
+            new StandardBundlerParam<> (
+            Arguments.CLIOptions.LINUX_BUNDLE_NAME.getId(),
+            String.class,
+            params -> {
+                String nm = APP_NAME.fetchFrom(params);
+                if (nm == null) return null;
+
+                // make sure to lower case and spaces become dashes
+                nm = nm.toLowerCase().replaceAll("[ ]", "-");
+
+                return nm;
+            },
+            (s, p) -> {
+                if (!RPM_PACKAGE_NAME_PATTERN.matcher(s).matches()) {
+                    String msgKey = "error.invalid-value-for-package-name";
+                    throw new IllegalArgumentException(
+                            new ConfigException(MessageFormat.format(
+                                    I18N.getString(msgKey), s),
+                                    I18N.getString(msgKey + ".advice")));
+                }
+
+                return s;
+            }
+        );
+
+    public static final BundlerParamInfo<String> LICENSE_TYPE =
+        new StandardBundlerParam<>(
+                Arguments.CLIOptions.LINUX_RPM_LICENSE_TYPE.getId(),
+                String.class,
+                params -> I18N.getString("param.license-type.default"),
+                (s, p) -> s
+        );
+
+    public static final BundlerParamInfo<String> GROUP =
+            new StandardBundlerParam<>(
+            Arguments.CLIOptions.LINUX_CATEGORY.getId(),
+            String.class,
+            params -> null,
+            (s, p) -> s);
+
+    private final static String DEFAULT_SPEC_TEMPLATE = "template.spec";
+
+    public final static String TOOL_RPM = "rpm";
+    public final static String TOOL_RPMBUILD = "rpmbuild";
+    public final static DottedVersion TOOL_RPMBUILD_MIN_VERSION = DottedVersion.lazy(
+            "4.0");
+
+    public LinuxRpmBundler() {
+        super(PACKAGE_NAME);
+    }
+
+    @Override
+    public void doValidate(Map<String, ? super Object> params)
+            throws ConfigException {
+    }
+
+    private static ToolValidator createRpmbuildToolValidator() {
+        Pattern pattern = Pattern.compile(" (\\d+\\.\\d+)");
+        return new ToolValidator(TOOL_RPMBUILD).setMinimalVersion(
+                TOOL_RPMBUILD_MIN_VERSION).setVersionParser(lines -> {
+                    String versionString = lines.limit(1).collect(
+                            Collectors.toList()).get(0);
+                    Matcher matcher = pattern.matcher(versionString);
+                    if (matcher.find()) {
+                        return matcher.group(1);
+                    }
+                    return null;
+                });
+    }
+
+    @Override
+    protected List<ToolValidator> getToolValidators(
+            Map<String, ? super Object> params) {
+        return List.of(createRpmbuildToolValidator());
+    }
+
+    @Override
+    protected File buildPackageBundle(
+            Map<String, String> replacementData,
+            Map<String, ? super Object> params, File outputParentDir) throws
+            PackagerException, IOException {
+
+        Path specFile = specFile(params);
+
+        // prepare spec file
+        createResource(DEFAULT_SPEC_TEMPLATE, params)
+                .setCategory(I18N.getString("resource.rpm-spec-file"))
+                .setSubstitutionData(replacementData)
+                .saveToFile(specFile);
+
+        return buildRPM(params, outputParentDir.toPath()).toFile();
+    }
+
+    @Override
+    protected Map<String, String> createReplacementData(
+            Map<String, ? super Object> params) throws IOException {
+        Map<String, String> data = new HashMap<>();
+
+        data.put("APPLICATION_DIRECTORY", Path.of(LINUX_INSTALL_DIR.fetchFrom(
+                params), PACKAGE_NAME.fetchFrom(params)).toString());
+        data.put("APPLICATION_SUMMARY", APP_NAME.fetchFrom(params));
+        data.put("APPLICATION_LICENSE_TYPE", LICENSE_TYPE.fetchFrom(params));
+
+        String licenseFile = LICENSE_FILE.fetchFrom(params);
+        if (licenseFile != null) {
+            licenseFile = Path.of(licenseFile).toAbsolutePath().normalize().toString();
+        }
+        data.put("APPLICATION_LICENSE_FILE", licenseFile);
+        data.put("APPLICATION_GROUP", GROUP.fetchFrom(params));
+
+        return data;
+    }
+
+    @Override
+    protected void initLibProvidersLookup(
+            Map<String, ? super Object> params,
+            LibProvidersLookup libProvidersLookup) {
+        libProvidersLookup.setPackageLookup(file -> {
+            return Executor.of(TOOL_RPM,
+                "-q", "--queryformat", "%{name}\\n",
+                "-q", "--whatprovides", file.toString())
+                .saveOutput(true).executeExpectSuccess().getOutput().stream();
+        });
+    }
+
+    @Override
+    protected List<ConfigException> verifyOutputBundle(
+            Map<String, ? super Object> params, Path packageBundle) {
+        List<ConfigException> errors = new ArrayList<>();
+
+        String specFileName = specFile(params).getFileName().toString();
+
+        try {
+            List<PackageProperty> properties = List.of(
+                    new PackageProperty("Name", PACKAGE_NAME.fetchFrom(params),
+                            "APPLICATION_PACKAGE", specFileName),
+                    new PackageProperty("Version", VERSION.fetchFrom(params),
+                            "APPLICATION_VERSION", specFileName),
+                    new PackageProperty("Release", RELEASE.fetchFrom(params),
+                            "APPLICATION_RELEASE", specFileName),
+                    new PackageProperty("Arch", rpmArch(), null, specFileName));
+
+            List<String> actualValues = Executor.of(TOOL_RPM, "-qp", "--queryformat",
+                    properties.stream().map(entry -> String.format("%%{%s}",
+                    entry.name)).collect(Collectors.joining("\\n")),
+                    packageBundle.toString()).saveOutput(true).executeExpectSuccess().getOutput();
+
+            Iterator<String> actualValuesIt = actualValues.iterator();
+            properties.forEach(property -> errors.add(property.verifyValue(
+                    actualValuesIt.next())));
+        } catch (IOException ex) {
+            // Ignore error as it is not critical. Just report it.
+            Log.verbose(ex);
+        }
+
+        return errors;
+    }
+
+    /**
+     * Various ways to get rpm arch. Needed to address JDK-8233143. rpmbuild is
+     * mandatory for rpm packaging, try it first. rpm is optional and may not be
+     * available, use as the last resort.
+     */
+    private enum RpmArchReader {
+        Rpmbuild(TOOL_RPMBUILD, "--eval=%{_target_cpu}"),
+        Rpm(TOOL_RPM, "--eval=%{_target_cpu}");
+
+        RpmArchReader(String... cmdline) {
+            this.cmdline = cmdline;
+        }
+
+        String getRpmArch() throws IOException {
+            Executor exec = Executor.of(cmdline).saveOutput(true);
+            if (this == values()[values().length - 1]) {
+                exec.executeExpectSuccess();
+            } else if (exec.execute() != 0) {
+                return null;
+            }
+
+            return exec.getOutput().get(0);
+        }
+
+        private final String[] cmdline;
+    }
+
+    private String rpmArch() throws IOException {
+        if (rpmArch == null) {
+            for (var rpmArchReader : RpmArchReader.values()) {
+                rpmArch = rpmArchReader.getRpmArch();
+                if (rpmArch != null) {
+                    break;
+                }
+            }
+        }
+        return rpmArch;
+    }
+
+    private Path specFile(Map<String, ? super Object> params) {
+        return TEMP_ROOT.fetchFrom(params).toPath().resolve(Path.of("SPECS",
+                PACKAGE_NAME.fetchFrom(params) + ".spec"));
+    }
+
+    private Path buildRPM(Map<String, ? super Object> params,
+            Path outdir) throws IOException {
+
+        Path rpmFile = outdir.toAbsolutePath().resolve(String.format(
+                "%s-%s-%s.%s.rpm", PACKAGE_NAME.fetchFrom(params),
+                VERSION.fetchFrom(params), RELEASE.fetchFrom(params), rpmArch()));
+
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.outputting-bundle-location"),
+                rpmFile.getParent()));
+
+        PlatformPackage thePackage = createMetaPackage(params);
+
+        //run rpmbuild
+        Executor.of(
+                TOOL_RPMBUILD,
+                "-bb", specFile(params).toAbsolutePath().toString(),
+                "--define", String.format("%%_sourcedir %s",
+                        thePackage.sourceRoot()),
+                // save result to output dir
+                "--define", String.format("%%_rpmdir %s", rpmFile.getParent()),
+                // do not use other system directories to build as current user
+                "--define", String.format("%%_topdir %s",
+                        TEMP_ROOT.fetchFrom(params).toPath().toAbsolutePath()),
+                "--define", String.format("%%_rpmfilename %s", rpmFile.getFileName())
+        ).executeExpectSuccess();
+
+        Log.verbose(MessageFormat.format(
+                I18N.getString("message.output-bundle-location"),
+                rpmFile.getParent()));
+
+        return rpmFile;
+    }
+
+    @Override
+    public String getName() {
+        return I18N.getString("rpm.bundler.name");
+    }
+
+    @Override
+    public String getID() {
+        return "rpm";
+    }
+
+    @Override
+    public boolean supported(boolean runtimeInstaller) {
+        return Platform.isLinux() && (createRpmbuildToolValidator().validate() == null);
+    }
+
+    @Override
+    public boolean isDefault() {
+        return !LinuxDebBundler.isDebian();
+    }
+
+    private String rpmArch;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/PackageProperty.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.text.MessageFormat;
+
+final class PackageProperty {
+    /**
+     * Constructor
+     *
+     * @param name property name
+     * @param expectedValue expected property value
+     * @param substString substitution string to be placed in resource file to
+     * be replaced with the expected property value by jpackage at package build
+     * time
+     * @param customResource name of custom resource from resource directory in
+     * which this package property can be set
+     */
+    PackageProperty(String name, String expectedValue, String substString,
+            String customResource) {
+        this.name = name;
+        this.expectedValue = expectedValue;
+        this.substString = substString;
+        this.customResource = customResource;
+    }
+    
+    ConfigException verifyValue(String actualValue) {
+        if (expectedValue.equals(actualValue)) {
+            return null;
+        }
+        
+        final String advice;
+        if (substString != null) {
+            advice = MessageFormat.format(I18N.getString(
+                    "error.unexpected-package-property.advice"), substString,
+                    actualValue, name, customResource);
+        } else {
+            advice = MessageFormat.format(I18N.getString(
+                    "error.unexpected-default-package-property.advice"), name,
+                    customResource);
+        }
+        
+        return new ConfigException(MessageFormat.format(I18N.getString(
+                "error.unexpected-package-property"), name,
+                expectedValue, actualValue, customResource, substString), advice);
+    }
+
+    final String name;
+    private final String expectedValue;
+    private final String substString;
+    private final String customResource;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,69 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+app.bundler.name=Linux Application Image
+deb.bundler.name=DEB Bundle
+rpm.bundler.name=RPM Bundle
+
+param.license-type.default=Unknown
+param.menu-group.default=Unknown
+
+resource.deb-control-file=DEB control file
+resource.deb-preinstall-script=DEB preinstall script
+resource.deb-prerm-script=DEB prerm script
+resource.deb-postinstall-script=DEB postinstall script
+resource.deb-postrm-script=DEB postrm script
+resource.copyright-file=Copyright file
+resource.menu-shortcut-descriptor=Menu shortcut descriptor
+resource.menu-icon=menu icon
+resource.rpm-spec-file=RPM spec file
+
+error.tool-not-found.advice=Please install required packages
+error.tool-old-version.advice=Please install required packages
+
+error.invalid-install-dir=Invalid installation directory "{0}"
+error.unsupported-install-dir=Installing to system directory "{0}" is currently unsupported
+
+error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}
+error.too-many-content-types-for-file-association=More than one MIME types was specified for File Association number {0}.
+error.invalid-value-for-package-name=Invalid value "{0}" for the bundle name.
+error.invalid-value-for-package-name.advice=Set the "linux-bundle-name" option to a valid Debian package name. Note that the package names must consist only of lower case letters (a-z), digits (0-9), plus (+) and minus (-) signs, and periods (.). They must be at least two characters long and must start with an alphanumeric character.
+
+message.icon-not-png=The specified icon "{0}" is not a PNG file and will not be used. The default icon will be used in it's place.
+message.test-for-tool=Test for [{0}]. Result: {1}
+message.outputting-to-location=Generating DEB for installer to: {0}.
+message.output-to-location=Package (.deb) saved to: {0}.
+message.debs-like-licenses=Debian packages should specify a license. The absence of a license will cause some linux distributions to complain about the quality of the application.
+message.outputting-bundle-location=Generating RPM for installer to: {0}.
+message.output-bundle-location=Package (.rpm) saved to: {0}.
+message.creating-association-with-null-extension=Creating association with null extension.
+
+message.ldd-not-available=ldd command not found. Package dependencies will not be generated.
+message.deb-ldd-not-available.advice=Install "libc-bin" DEB package to get ldd.
+message.rpm-ldd-not-available.advice=Install "glibc-common" RPM package to get ldd.
+
+error.unexpected-package-property=Expected value of "{0}" property is [{1}]. Actual value in output package is [{2}]. Looks like custom "{3}" file from resource directory contained hard coded value of "{0}" property
+error.unexpected-package-property.advice=Use [{0}] pattern string instead of hard coded value [{1}] of {2} property in custom "{3}" file
+error.unexpected-default-package-property.advice=Don't explicitly set value of {0} property in custom "{1}" file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_ja.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,69 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+app.bundler.name=Linux Application Image
+deb.bundler.name=DEB Bundle
+rpm.bundler.name=RPM Bundle
+
+param.license-type.default=Unknown
+param.menu-group.default=Unknown
+
+resource.deb-control-file=DEB control file
+resource.deb-preinstall-script=DEB preinstall script
+resource.deb-prerm-script=DEB prerm script
+resource.deb-postinstall-script=DEB postinstall script
+resource.deb-postrm-script=DEB postrm script
+resource.copyright-file=Copyright file
+resource.menu-shortcut-descriptor=Menu shortcut descriptor
+resource.menu-icon=menu icon
+resource.rpm-spec-file=RPM spec file
+
+error.tool-not-found.advice=Please install required packages
+error.tool-old-version.advice=Please install required packages
+
+error.invalid-install-dir=Invalid installation directory "{0}"
+error.unsupported-install-dir=Installing to system directory "{0}" is currently unsupported
+
+error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}
+error.too-many-content-types-for-file-association=More than one MIME types was specified for File Association number {0}.
+error.invalid-value-for-package-name=Invalid value "{0}" for the bundle name.
+error.invalid-value-for-package-name.advice=Set the "linux-bundle-name" option to a valid Debian package name. Note that the package names must consist only of lower case letters (a-z), digits (0-9), plus (+) and minus (-) signs, and periods (.). They must be at least two characters long and must start with an alphanumeric character.
+
+message.icon-not-png=The specified icon "{0}" is not a PNG file and will not be used. The default icon will be used in it's place.
+message.test-for-tool=Test for [{0}]. Result: {1}
+message.outputting-to-location=Generating DEB for installer to: {0}.
+message.output-to-location=Package (.deb) saved to: {0}.
+message.debs-like-licenses=Debian packages should specify a license. The absence of a license will cause some linux distributions to complain about the quality of the application.
+message.outputting-bundle-location=Generating RPM for installer to: {0}.
+message.output-bundle-location=Package (.rpm) saved to: {0}.
+message.creating-association-with-null-extension=Creating association with null extension.
+
+message.ldd-not-available=ldd command not found. Package dependencies will not be generated.
+message.deb-ldd-not-available.advice=Install "libc-bin" DEB package to get ldd.
+message.rpm-ldd-not-available.advice=Install "glibc-common" RPM package to get ldd.
+
+error.unexpected-package-property=Expected value of "{0}" property is [{1}]. Actual value in output package is [{2}]. Looks like custom "{3}" file from resource directory contained hard coded value of "{0}" property
+error.unexpected-package-property.advice=Use [{0}] pattern string instead of hard coded value [{1}] of {2} property in custom "{3}" file
+error.unexpected-default-package-property.advice=Don't explicitly set value of {0} property in custom "{1}" file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/LinuxResources_zh_CN.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,69 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+app.bundler.name=Linux Application Image
+deb.bundler.name=DEB Bundle
+rpm.bundler.name=RPM Bundle
+
+param.license-type.default=Unknown
+param.menu-group.default=Unknown
+
+resource.deb-control-file=DEB control file
+resource.deb-preinstall-script=DEB preinstall script
+resource.deb-prerm-script=DEB prerm script
+resource.deb-postinstall-script=DEB postinstall script
+resource.deb-postrm-script=DEB postrm script
+resource.copyright-file=Copyright file
+resource.menu-shortcut-descriptor=Menu shortcut descriptor
+resource.menu-icon=menu icon
+resource.rpm-spec-file=RPM spec file
+
+error.tool-not-found.advice=Please install required packages
+error.tool-old-version.advice=Please install required packages
+
+error.invalid-install-dir=Invalid installation directory "{0}"
+error.unsupported-install-dir=Installing to system directory "{0}" is currently unsupported
+
+error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}
+error.too-many-content-types-for-file-association=More than one MIME types was specified for File Association number {0}.
+error.invalid-value-for-package-name=Invalid value "{0}" for the bundle name.
+error.invalid-value-for-package-name.advice=Set the "linux-bundle-name" option to a valid Debian package name. Note that the package names must consist only of lower case letters (a-z), digits (0-9), plus (+) and minus (-) signs, and periods (.). They must be at least two characters long and must start with an alphanumeric character.
+
+message.icon-not-png=The specified icon "{0}" is not a PNG file and will not be used. The default icon will be used in it's place.
+message.test-for-tool=Test for [{0}]. Result: {1}
+message.outputting-to-location=Generating DEB for installer to: {0}.
+message.output-to-location=Package (.deb) saved to: {0}.
+message.debs-like-licenses=Debian packages should specify a license. The absence of a license will cause some linux distributions to complain about the quality of the application.
+message.outputting-bundle-location=Generating RPM for installer to: {0}.
+message.output-bundle-location=Package (.rpm) saved to: {0}.
+message.creating-association-with-null-extension=Creating association with null extension.
+
+message.ldd-not-available=ldd command not found. Package dependencies will not be generated.
+message.deb-ldd-not-available.advice=Install "libc-bin" DEB package to get ldd.
+message.rpm-ldd-not-available.advice=Install "glibc-common" RPM package to get ldd.
+
+error.unexpected-package-property=Expected value of "{0}" property is [{1}]. Actual value in output package is [{2}]. Looks like custom "{3}" file from resource directory contained hard coded value of "{0}" property
+error.unexpected-package-property.advice=Use [{0}] pattern string instead of hard coded value [{1}] of {2} property in custom "{3}" file
+error.unexpected-default-package-property.advice=Don't explicitly set value of {0} property in custom "{1}" file
Binary file src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/java32.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.control	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,10 @@
+Package: APPLICATION_PACKAGE
+Version: APPLICATION_VERSION-APPLICATION_RELEASE
+Section: APPLICATION_SECTION
+Maintainer: APPLICATION_MAINTAINER
+Priority: optional
+Architecture: APPLICATION_ARCH
+Provides: APPLICATION_PACKAGE
+Description: APPLICATION_DESCRIPTION
+Depends: PACKAGE_DEFAULT_DEPENDENCIES PACKAGE_CUSTOM_DEPENDENCIES
+Installed-Size: APPLICATION_INSTALLED_SIZE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.copyright	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,5 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+
+Files: *
+Copyright: APPLICATION_COPYRIGHT
+License: APPLICATION_LICENSE_TEXT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.desktop	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Name=APPLICATION_NAME
+Comment=APPLICATION_DESCRIPTION
+Exec=APPLICATION_LAUNCHER
+Icon=APPLICATION_ICON
+Terminal=false
+Type=Application
+Categories=DEPLOY_BUNDLE_CATEGORY
+DESKTOP_MIMES
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.postinst	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,34 @@
+#!/bin/sh
+# postinst script for APPLICATION_PACKAGE
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <postinst> `configure' <most-recently-configured-version>
+#        * <old-postinst> `abort-upgrade' <new version>
+#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+#          <new-version>
+#        * <postinst> `abort-remove'
+#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+#          <failed-install-package> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+case "$1" in
+    configure)
+DESKTOP_COMMANDS_INSTALL
+    ;;
+
+    abort-upgrade|abort-remove|abort-deconfigure)
+    ;;
+
+    *)
+        echo "postinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.postrm	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,31 @@
+#!/bin/sh
+# postrm script for APPLICATION_PACKAGE
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <postrm> `remove'
+#        * <postrm> `purge'
+#        * <old-postrm> `upgrade' <new-version>
+#        * <new-postrm> `failed-upgrade' <old-version>
+#        * <new-postrm> `abort-install'
+#        * <new-postrm> `abort-install' <old-version>
+#        * <new-postrm> `abort-upgrade' <old-version>
+#        * <disappearer's-postrm> `disappear' <overwriter>
+#          <overwriter-version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+case "$1" in
+    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+    ;;
+
+    *)
+        echo "postrm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.preinst	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,30 @@
+#!/bin/sh
+# preinst script for APPLICATION_PACKAGE
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <new-preinst> `install'
+#        * <new-preinst> `install' <old-version>
+#        * <new-preinst> `upgrade' <old-version>
+#        * <old-preinst> `abort-upgrade' <new-version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+    install|upgrade)
+    ;;
+
+    abort-upgrade)
+    ;;
+
+    *)
+        echo "preinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.prerm	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,37 @@
+#!/bin/sh
+# prerm script for APPLICATION_PACKAGE
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <prerm> `remove'
+#        * <old-prerm> `upgrade' <new-version>
+#        * <new-prerm> `failed-upgrade' <old-version>
+#        * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
+#        * <deconfigured's-prerm> `deconfigure' `in-favour'
+#          <package-being-installed> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+UTILITY_SCRIPTS
+
+case "$1" in
+    remove|upgrade|deconfigure)
+DESKTOP_COMMANDS_UNINSTALL
+    ;;
+
+    failed-upgrade)
+    ;;
+
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+exit 0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/template.spec	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,58 @@
+Summary: APPLICATION_SUMMARY
+Name: APPLICATION_PACKAGE
+Version: APPLICATION_VERSION
+Release: APPLICATION_RELEASE
+License: APPLICATION_LICENSE_TYPE
+Vendor: APPLICATION_VENDOR
+Prefix: %{dirname:APPLICATION_DIRECTORY}
+Provides: APPLICATION_PACKAGE
+%if "xAPPLICATION_GROUP" != x
+Group: APPLICATION_GROUP
+%endif
+
+Autoprov: 0
+Autoreq: 0
+%if "xPACKAGE_DEFAULT_DEPENDENCIES" != x || "xPACKAGE_CUSTOM_DEPENDENCIES" != x
+Requires: PACKAGE_DEFAULT_DEPENDENCIES PACKAGE_CUSTOM_DEPENDENCIES
+%endif
+
+#comment line below to enable effective jar compression
+#it could easily get your package size from 40 to 15Mb but
+#build time will substantially increase and it may require unpack200/system java to install
+%define __jar_repack %{nil}
+
+%description
+APPLICATION_DESCRIPTION
+
+%prep
+
+%build
+
+%install
+rm -rf %{buildroot}
+install -d -m 755 %{buildroot}APPLICATION_DIRECTORY
+cp -r %{_sourcedir}APPLICATION_DIRECTORY/* %{buildroot}APPLICATION_DIRECTORY
+%if "xAPPLICATION_LICENSE_FILE" != x
+  %define license_install_file %{_defaultlicensedir}/%{name}-%{version}/%{basename:APPLICATION_LICENSE_FILE}
+  install -d -m 755 %{buildroot}%{dirname:%{license_install_file}}
+  install -m 644 APPLICATION_LICENSE_FILE %{buildroot}%{license_install_file}
+%endif
+
+%files
+%if "xAPPLICATION_LICENSE_FILE" != x
+  %license %{license_install_file}
+  %{dirname:%{license_install_file}}
+%endif
+# If installation directory for the application is /a/b/c, we want only root
+# component of the path (/a) in the spec file to make sure all subdirectories
+# are owned by the package.
+%(echo APPLICATION_DIRECTORY | sed -e "s|\(^/[^/]\{1,\}\).*$|\1|")
+
+%post
+DESKTOP_COMMANDS_INSTALL
+
+%preun
+UTILITY_SCRIPTS
+DESKTOP_COMMANDS_UNINSTALL
+
+%clean
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/resources/utils.sh	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,104 @@
+#
+# Remove $1 desktop file from the list of default handlers for $2 mime type
+# in $3 file dumping output to stdout.
+#
+_filter_out_default_mime_handler ()
+{
+  local defaults_list="$3"
+
+  local desktop_file="$1"
+  local mime_type="$2"
+
+  awk -f- "$defaults_list" <<EOF
+  BEGIN {
+    mime_type="$mime_type"
+    mime_type_regexp="~" mime_type "="
+    desktop_file="$desktop_file"
+  }
+  \$0 ~ mime_type {
+    \$0 = substr(\$0, length(mime_type) + 2);
+    split(\$0, desktop_files, ";")
+    remaining_desktop_files
+    counter=0
+    for (idx in desktop_files) {
+      if (desktop_files[idx] != desktop_file) {
+        ++counter;
+      }
+    }
+    if (counter) {
+      printf mime_type "="
+      for (idx in desktop_files) {
+        if (desktop_files[idx] != desktop_file) {
+          printf desktop_files[idx]
+          if (--counter) {
+            printf ";"
+          }
+        }
+      }
+      printf "\n"
+    }
+    next
+  }
+
+  { print }
+EOF
+}
+
+
+#
+# Remove $2 desktop file from the list of default handlers for $@ mime types
+# in $1 file.
+# Result is saved in $1 file.
+#
+_uninstall_default_mime_handler ()
+{
+  local defaults_list=$1
+  shift
+  [ -f "$defaults_list" ] || return 0
+
+  local desktop_file="$1"
+  shift
+
+  tmpfile1=$(mktemp)
+  tmpfile2=$(mktemp)
+  cat "$defaults_list" > "$tmpfile1"
+
+  local v
+  local update=
+  for mime in "$@"; do
+    _filter_out_default_mime_handler "$desktop_file" "$mime" "$tmpfile1" > "$tmpfile2"
+    v="$tmpfile2"
+    tmpfile2="$tmpfile1"
+    tmpfile1="$v"
+
+    if ! diff -q "$tmpfile1" "$tmpfile2" > /dev/null; then
+      update=yes
+      trace Remove $desktop_file default handler for $mime mime type from $defaults_list file
+    fi
+  done
+
+  if [ -n "$update" ]; then
+    cat "$tmpfile1" > "$defaults_list"
+    trace "$defaults_list" file updated
+  fi
+
+  rm -f "$tmpfile1" "$tmpfile2"
+}
+
+
+#
+# Remove $1 desktop file from the list of default handlers for $@ mime types
+# in all known system defaults lists.
+#
+uninstall_default_mime_handler ()
+{
+  for f in /usr/share/applications/defaults.list /usr/local/share/applications/defaults.list; do
+    _uninstall_default_mime_handler "$f" "$@"
+  done
+}
+
+
+trace ()
+{
+  echo "$@"
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/classes/module-info.java.extra	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+
+provides jdk.incubator.jpackage.internal.Bundler with
+    jdk.incubator.jpackage.internal.LinuxAppBundler,
+    jdk.incubator.jpackage.internal.LinuxDebBundler,
+    jdk.incubator.jpackage.internal.LinuxRpmBundler;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/native/jpackageapplauncher/launcher.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include <dlfcn.h>
+#include <locale.h>
+#include <string>
+#include <libgen.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+typedef bool (*start_launcher)(int argc, char* argv[]);
+typedef void (*stop_launcher)();
+
+#define MAX_PATH 1024
+
+std::string GetProgramPath() {
+    ssize_t len = 0;
+    std::string result;
+    char buffer[MAX_PATH] = {0};
+
+    if ((len = readlink("/proc/self/exe", buffer, MAX_PATH - 1)) != -1) {
+        buffer[len] = '\0';
+        result = buffer;
+    }
+
+    return result;
+}
+
+int main(int argc, char *argv[]) {
+    int result = 1;
+    setlocale(LC_ALL, "en_US.utf8");
+    void* library = NULL;
+
+    {
+        std::string programPath = GetProgramPath();
+        std::string libraryName = dirname((char*)programPath.c_str());
+        libraryName += "/../lib/libapplauncher.so";
+        library = dlopen(libraryName.c_str(), RTLD_LAZY);
+
+        if (library == NULL) {
+            fprintf(stderr, "dlopen failed: %s\n", dlerror());
+            fprintf(stderr, "%s not found.\n", libraryName.c_str());
+        }
+    }
+
+    if (library != NULL) {
+        start_launcher start = (start_launcher)dlsym(library, "start_launcher");
+        stop_launcher stop = (stop_launcher)dlsym(library, "stop_launcher");
+
+        if (start != NULL && stop != NULL) {
+            if (start(argc, argv) == true) {
+                result = 0;
+                stop();
+            }
+        } else {
+            fprintf(stderr, "cannot find start_launcher and stop_launcher in libapplauncher.so");
+        }
+
+        dlclose(library);
+    }
+
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/native/libapplauncher/LinuxPlatform.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,1080 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "Platform.h"
+
+#include "JavaVirtualMachine.h"
+#include "LinuxPlatform.h"
+#include "PlatformString.h"
+#include "IniFile.h"
+#include "Helpers.h"
+#include "FilePath.h"
+
+#include <stdlib.h>
+#include <pwd.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <signal.h>
+
+#define LINUX_JPACKAGE_TMP_DIR "/.java/jpackage/tmp"
+
+TString GetEnv(const TString &name) {
+    TString result;
+
+    char *value = ::getenv((TCHAR*) name.c_str());
+
+    if (value != NULL) {
+        result = value;
+    }
+
+    return result;
+}
+
+LinuxPlatform::LinuxPlatform(void) : Platform(),
+PosixPlatform() {
+    FMainThread = pthread_self();
+}
+
+LinuxPlatform::~LinuxPlatform(void) {
+}
+
+TString LinuxPlatform::GetPackageAppDirectory() {
+    return FilePath::IncludeTrailingSeparator(
+            GetPackageRootDirectory()) + _T("lib/app");
+}
+
+TString LinuxPlatform::GetAppName() {
+    TString result = GetModuleFileName();
+    result = FilePath::ExtractFileName(result);
+    return result;
+}
+
+TString LinuxPlatform::GetPackageLauncherDirectory() {
+    return FilePath::IncludeTrailingSeparator(
+            GetPackageRootDirectory()) + _T("bin");
+}
+
+TString LinuxPlatform::GetPackageRuntimeBinDirectory() {
+    return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory())
+            + _T("runtime/bin");
+}
+
+void LinuxPlatform::ShowMessage(TString title, TString description) {
+    printf("%s %s\n", PlatformString(title).toPlatformString(),
+            PlatformString(description).toPlatformString());
+    fflush(stdout);
+}
+
+void LinuxPlatform::ShowMessage(TString description) {
+    TString appname = GetModuleFileName();
+    appname = FilePath::ExtractFileName(appname);
+    ShowMessage(PlatformString(appname).toPlatformString(),
+            PlatformString(description).toPlatformString());
+}
+
+TCHAR* LinuxPlatform::ConvertStringToFileSystemString(TCHAR* Source,
+        bool &release) {
+    // Not Implemented.
+    return NULL;
+}
+
+TCHAR* LinuxPlatform::ConvertFileSystemStringToString(TCHAR* Source,
+        bool &release) {
+    // Not Implemented.
+    return NULL;
+}
+
+TString LinuxPlatform::GetModuleFileName() {
+    ssize_t len = 0;
+    TString result;
+    DynamicBuffer<TCHAR> buffer(MAX_PATH);
+    if (buffer.GetData() == NULL) {
+        return result;
+    }
+
+    if ((len = readlink("/proc/self/exe", buffer.GetData(),
+            MAX_PATH - 1)) != -1) {
+        buffer[len] = '\0';
+        result = buffer.GetData();
+    }
+
+    return result;
+}
+
+TString LinuxPlatform::GetPackageRootDirectory() {
+    TString result;
+    TString filename = GetModuleFileName();
+    TString binPath = FilePath::ExtractFilePath(filename);
+
+    size_t slash = binPath.find_last_of(TRAILING_PATHSEPARATOR);
+    if (slash != TString::npos) {
+        result = binPath.substr(0, slash);
+    }
+
+    return result;
+}
+
+TString LinuxPlatform::GetAppDataDirectory() {
+    TString result;
+    TString home = GetEnv(_T("HOME"));
+
+    if (home.empty() == false) {
+        result += FilePath::IncludeTrailingSeparator(home) + _T(".local");
+    }
+
+    return result;
+}
+
+ISectionalPropertyContainer* LinuxPlatform::GetConfigFile(TString FileName) {
+    IniFile *result = new IniFile();
+    if (result == NULL) {
+        return NULL;
+    }
+
+    result->LoadFromFile(FileName);
+
+    return result;
+}
+
+TString LinuxPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) {
+    TString result = FilePath::IncludeTrailingSeparator(RuntimePath) +
+            "lib/libjli.so";
+
+    if (FilePath::FileExists(result) == false) {
+        result = FilePath::IncludeTrailingSeparator(RuntimePath) +
+                "lib/jli/libjli.so";
+        if (FilePath::FileExists(result) == false) {
+            printf("Cannot find libjli.so!");
+        }
+    }
+
+    return result;
+}
+
+bool LinuxPlatform::IsMainThread() {
+    bool result = (FMainThread == pthread_self());
+    return result;
+}
+
+TString LinuxPlatform::getTmpDirString() {
+    return TString(LINUX_JPACKAGE_TMP_DIR);
+}
+
+TPlatformNumber LinuxPlatform::GetMemorySize() {
+    long pages = sysconf(_SC_PHYS_PAGES);
+    long page_size = sysconf(_SC_PAGE_SIZE);
+    TPlatformNumber result = pages * page_size;
+    result = result / 1048576; // Convert from bytes to megabytes.
+    return result;
+}
+
+void PosixProcess::Cleanup() {
+    if (FOutputHandle != 0) {
+        close(FOutputHandle);
+        FOutputHandle = 0;
+    }
+
+    if (FInputHandle != 0) {
+        close(FInputHandle);
+        FInputHandle = 0;
+    }
+}
+
+#define PIPE_READ 0
+#define PIPE_WRITE 1
+
+bool PosixProcess::Execute(const TString Application,
+        const std::vector<TString> Arguments, bool AWait) {
+    bool result = false;
+
+    if (FRunning == false) {
+        FRunning = true;
+
+        int handles[2];
+
+        if (pipe(handles) == -1) {
+            return false;
+        }
+
+        struct sigaction sa;
+        sa.sa_handler = SIG_IGN;
+        sigemptyset(&sa.sa_mask);
+        sa.sa_flags = 0;
+
+        FChildPID = fork();
+
+        // PID returned by vfork is 0 for the child process and the
+        // PID of the child process for the parent.
+        if (FChildPID == -1) {
+            // Error
+            TString message = PlatformString::Format(
+                    _T("Error: Unable to create process %s"),
+                    Application.data());
+            throw Exception(message);
+        } else if (FChildPID == 0) {
+            Cleanup();
+            TString command = Application;
+
+            for (std::vector<TString>::const_iterator iterator =
+                    Arguments.begin(); iterator != Arguments.end();
+                    iterator++) {
+                command += TString(_T(" ")) + *iterator;
+            }
+#ifdef DEBUG
+            printf("%s\n", command.data());
+#endif // DEBUG
+
+            dup2(handles[PIPE_READ], STDIN_FILENO);
+            dup2(handles[PIPE_WRITE], STDOUT_FILENO);
+
+            close(handles[PIPE_READ]);
+            close(handles[PIPE_WRITE]);
+
+            execl("/bin/sh", "sh", "-c", command.data(), (char *) 0);
+
+            _exit(127);
+        } else {
+            FOutputHandle = handles[PIPE_READ];
+            FInputHandle = handles[PIPE_WRITE];
+
+            if (AWait == true) {
+                ReadOutput();
+                Wait();
+                Cleanup();
+                FRunning = false;
+                result = true;
+            } else {
+                result = true;
+            }
+        }
+    }
+
+    return result;
+}
+
+
+//----------------------------------------------------------------------------
+
+#ifndef __UNIX_JPACKAGE_PLATFORM__
+#define __UNIX_JPACKAGE_PLATFORM__
+
+/** Provide an abstraction for difference in the platform APIs,
+     e.g. string manipulation functions, etc. */
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/stat.h>
+
+#define TCHAR char
+
+#define _T(x) x
+
+#define JPACKAGE_MULTIBYTE_SNPRINTF snprintf
+
+#define JPACKAGE_SNPRINTF(buffer, sizeOfBuffer, count, format, ...) \
+    snprintf((buffer), (count), (format), __VA_ARGS__)
+
+#define JPACKAGE_PRINTF(format, ...) \
+    printf((format), ##__VA_ARGS__)
+
+#define JPACKAGE_FPRINTF(dest, format, ...) \
+    fprintf((dest), (format), __VA_ARGS__)
+
+#define JPACKAGE_SSCANF(buf, format, ...) \
+    sscanf((buf), (format), __VA_ARGS__)
+
+#define JPACKAGE_STRDUP(strSource) \
+    strdup((strSource))
+
+//return "error code" (like on Windows)
+
+static int JPACKAGE_STRNCPY(char *strDest, size_t numberOfElements,
+        const char *strSource, size_t count) {
+    char *s = strncpy(strDest, strSource, count);
+    // Duplicate behavior of the Windows' _tcsncpy_s() by adding a NULL
+    // terminator at the end of the string.
+    if (count < numberOfElements) {
+        s[count] = '\0';
+    } else {
+        s[numberOfElements - 1] = '\0';
+    }
+    return (s == strDest) ? 0 : 1;
+}
+
+#define JPACKAGE_STRICMP(x, y) \
+    strcasecmp((x), (y))
+
+#define JPACKAGE_STRNICMP(x, y, cnt) \
+    strncasecmp((x), (y), (cnt))
+
+#define JPACKAGE_STRNCMP(x, y, cnt) \
+    strncmp((x), (y), (cnt))
+
+#define JPACKAGE_STRLEN(x) \
+    strlen((x))
+
+#define JPACKAGE_STRSTR(x, y) \
+    strstr((x), (y))
+
+#define JPACKAGE_STRCHR(x, y) \
+    strchr((x), (y))
+
+#define JPACKAGE_STRRCHR(x, y) \
+    strrchr((x), (y))
+
+#define JPACKAGE_STRPBRK(x, y) \
+    strpbrk((x), (y))
+
+#define JPACKAGE_GETENV(x) \
+    getenv((x))
+
+#define JPACKAGE_PUTENV(x) \
+    putenv((x))
+
+#define JPACKAGE_STRCMP(x, y) \
+    strcmp((x), (y))
+
+#define JPACKAGE_STRCPY(x, y) \
+    strcpy((x), (y))
+
+#define JPACKAGE_STRCAT(x, y) \
+    strcat((x), (y))
+
+#define JPACKAGE_ATOI(x) \
+    atoi((x))
+
+#define JPACKAGE_FOPEN(x, y) \
+    fopen((x), (y))
+
+#define JPACKAGE_FGETS(x, y, z) \
+    fgets((x), (y), (z))
+
+#define JPACKAGE_REMOVE(x) \
+    remove((x))
+
+#define JPACKAGE_SPAWNV(mode, cmd, args) \
+    spawnv((mode), (cmd), (args))
+
+#define JPACKAGE_ISDIGIT(ch) isdigit(ch)
+
+// for non-unicode, just return the input string for
+// the following 2 conversions
+#define JPACKAGE_NEW_MULTIBYTE(message) message
+
+#define JPACKAGE_NEW_FROM_MULTIBYTE(message) message
+
+// for non-unicode, no-op for the relase operation
+// since there is no memory allocated for the
+// string conversions
+#define JPACKAGE_RELEASE_MULTIBYTE(tmpMBCS)
+
+#define JPACKAGE_RELEASE_FROM_MULTIBYTE(tmpMBCS)
+
+// The size will be used for converting from 1 byte to 1 byte encoding.
+// Ensure have space for zero-terminator.
+#define JPACKAGE_GET_SIZE_FOR_ENCODING(message, theLength) (theLength + 1)
+
+#endif
+#define xmlTagType    0
+#define xmlPCDataType 1
+
+typedef struct _xmlNode XMLNode;
+typedef struct _xmlAttribute XMLAttribute;
+
+struct _xmlNode {
+    int _type; // Type of node: tag, pcdata, cdate
+    TCHAR* _name; // Contents of node
+    XMLNode* _next; // Next node at same level
+    XMLNode* _sub; // First sub-node
+    XMLAttribute* _attributes; // List of attributes
+};
+
+struct _xmlAttribute {
+    TCHAR* _name; // Name of attribute
+    TCHAR* _value; // Value of attribute
+    XMLAttribute* _next; // Next attribute for this tag
+};
+
+// Public interface
+static void RemoveNonAsciiUTF8FromBuffer(char *buf);
+XMLNode* ParseXMLDocument(TCHAR* buf);
+void FreeXMLDocument(XMLNode* root);
+
+// Utility methods for parsing document
+XMLNode* FindXMLChild(XMLNode* root, const TCHAR* name);
+TCHAR* FindXMLAttribute(XMLAttribute* attr, const TCHAR* name);
+
+// Debugging
+void PrintXMLDocument(XMLNode* node, int indt);
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <wctype.h>
+
+#define JWS_assert(s, msg)      \
+    if (!(s)) { Abort(msg); }
+
+
+// Internal declarations
+static XMLNode* ParseXMLElement(void);
+static XMLAttribute* ParseXMLAttribute(void);
+static TCHAR* SkipWhiteSpace(TCHAR *p);
+static TCHAR* SkipXMLName(TCHAR *p);
+static TCHAR* SkipXMLComment(TCHAR *p);
+static TCHAR* SkipXMLDocType(TCHAR *p);
+static TCHAR* SkipXMLProlog(TCHAR *p);
+static TCHAR* SkipPCData(TCHAR *p);
+static int IsPCData(TCHAR *p);
+static void ConvertBuiltInEntities(TCHAR* p);
+static void SetToken(int type, TCHAR* start, TCHAR* end);
+static void GetNextToken(void);
+static XMLNode* CreateXMLNode(int type, TCHAR* name);
+static XMLAttribute* CreateXMLAttribute(TCHAR *name, TCHAR* value);
+static XMLNode* ParseXMLElement(void);
+static XMLAttribute* ParseXMLAttribute(void);
+static void FreeXMLAttribute(XMLAttribute* attr);
+static void PrintXMLAttributes(XMLAttribute* attr);
+static void indent(int indt);
+
+static jmp_buf jmpbuf;
+static XMLNode* root_node = NULL;
+
+/** definition of error codes for setjmp/longjmp,
+ *  that can be handled in ParseXMLDocument()
+ */
+#define JMP_NO_ERROR     0
+#define JMP_OUT_OF_RANGE 1
+
+#define NEXT_CHAR(p) { \
+    if (*p != 0) { \
+        p++; \
+    } else { \
+        longjmp(jmpbuf, JMP_OUT_OF_RANGE); \
+    } \
+}
+#define NEXT_CHAR_OR_BREAK(p) { \
+    if (*p != 0) { \
+        p++; \
+    } else { \
+        break; \
+    } \
+}
+#define NEXT_CHAR_OR_RETURN(p) { \
+    if (*p != 0) { \
+        p++; \
+    } else { \
+        return; \
+    } \
+}
+#define SKIP_CHARS(p,n) { \
+    int i; \
+    for (i = 0; i < (n); i++) { \
+        if (*p != 0) { \
+            p++; \
+        } else { \
+           longjmp(jmpbuf, JMP_OUT_OF_RANGE); \
+        } \
+    } \
+}
+#define SKIP_CHARS_OR_BREAK(p,n) { \
+    int i; \
+    for (i = 0; i < (n); i++) { \
+        if (*p != 0) { \
+            p++; \
+        } else { \
+            break; \
+        } \
+    } \
+    if (i < (n)) { \
+        break; \
+    } \
+}
+
+/** Iterates through the null-terminated buffer (i.e., C string) and
+ *  replaces all UTF-8 encoded character >255 with 255
+ *
+ *  UTF-8 encoding:
+ *
+ *   Range A:  0x0000 - 0x007F
+ *                               0 | bits 0 - 7
+ *   Range B : 0x0080 - 0x07FF  :
+ *                               110 | bits 6 - 10
+ *                               10  | bits 0 - 5
+ *   Range C : 0x0800 - 0xFFFF  :
+ *                               1110 | bits 12-15
+ *                               10   | bits  6-11
+ *                               10   | bits  0-5
+ */
+static void RemoveNonAsciiUTF8FromBuffer(char *buf) {
+    char* p;
+    char* q;
+    char c;
+    p = q = buf;
+    // We are not using NEXT_CHAR() to check if *q is NULL, as q is output
+    // location and offset for q is smaller than for p.
+    while (*p != '\0') {
+        c = *p;
+        if ((c & 0x80) == 0) {
+            /* Range A */
+            *q++ = *p;
+            NEXT_CHAR(p);
+        } else if ((c & 0xE0) == 0xC0) {
+            /* Range B */
+            *q++ = (char) 0xFF;
+            NEXT_CHAR(p);
+            NEXT_CHAR_OR_BREAK(p);
+        } else {
+            /* Range C */
+            *q++ = (char) 0xFF;
+            NEXT_CHAR(p);
+            SKIP_CHARS_OR_BREAK(p, 2);
+        }
+    }
+    /* Null terminate string */
+    *q = '\0';
+}
+
+static TCHAR* SkipWhiteSpace(TCHAR *p) {
+    if (p != NULL) {
+        while (iswspace(*p))
+            NEXT_CHAR_OR_BREAK(p);
+    }
+    return p;
+}
+
+static TCHAR* SkipXMLName(TCHAR *p) {
+    TCHAR c = *p;
+    /* Check if start of token */
+    if (('a' <= c && c <= 'z') ||
+            ('A' <= c && c <= 'Z') ||
+            c == '_' || c == ':') {
+
+        while (('a' <= c && c <= 'z') ||
+                ('A' <= c && c <= 'Z') ||
+                ('0' <= c && c <= '9') ||
+                c == '_' || c == ':' || c == '.' || c == '-') {
+            NEXT_CHAR(p);
+            c = *p;
+            if (c == '\0') break;
+        }
+    }
+    return p;
+}
+
+static TCHAR* SkipXMLComment(TCHAR *p) {
+    if (p != NULL) {
+        if (JPACKAGE_STRNCMP(p, _T("<!--"), 4) == 0) {
+            SKIP_CHARS(p, 4);
+            do {
+                if (JPACKAGE_STRNCMP(p, _T("-->"), 3) == 0) {
+                    SKIP_CHARS(p, 3);
+                    return p;
+                }
+                NEXT_CHAR(p);
+            } while (*p != '\0');
+        }
+    }
+    return p;
+}
+
+static TCHAR* SkipXMLDocType(TCHAR *p) {
+    if (p != NULL) {
+        if (JPACKAGE_STRNCMP(p, _T("<!"), 2) == 0) {
+            SKIP_CHARS(p, 2);
+            while (*p != '\0') {
+                if (*p == '>') {
+                    NEXT_CHAR(p);
+                    return p;
+                }
+                NEXT_CHAR(p);
+            }
+        }
+    }
+    return p;
+}
+
+static TCHAR* SkipXMLProlog(TCHAR *p) {
+    if (p != NULL) {
+        if (JPACKAGE_STRNCMP(p, _T("<?"), 2) == 0) {
+            SKIP_CHARS(p, 2);
+            do {
+                if (JPACKAGE_STRNCMP(p, _T("?>"), 2) == 0) {
+                    SKIP_CHARS(p, 2);
+                    return p;
+                }
+                NEXT_CHAR(p);
+            } while (*p != '\0');
+        }
+    }
+    return p;
+}
+
+/* Search for the built-in XML entities:
+ * &amp; (&), &lt; (<), &gt; (>), &apos; ('), and &quote(")
+ * and convert them to a real TCHARacter
+ */
+static void ConvertBuiltInEntities(TCHAR* p) {
+    TCHAR* q;
+    q = p;
+    // We are not using NEXT_CHAR() to check if *q is NULL,
+    // as q is output location and offset for q is smaller than for p.
+    while (*p) {
+        if (IsPCData(p)) {
+            /* dont convert &xxx values within PData */
+            TCHAR *end;
+            end = SkipPCData(p);
+            while (p < end) {
+                *q++ = *p;
+                NEXT_CHAR(p);
+            }
+        } else {
+            if (JPACKAGE_STRNCMP(p, _T("&amp;"), 5) == 0) {
+                *q++ = '&';
+                SKIP_CHARS(p, 5);
+            } else if (JPACKAGE_STRNCMP(p, _T("&lt;"), 4) == 0) {
+                *q = '<';
+                SKIP_CHARS(p, 4);
+            } else if (JPACKAGE_STRNCMP(p, _T("&gt;"), 4) == 0) {
+                *q = '>';
+                SKIP_CHARS(p, 4);
+            } else if (JPACKAGE_STRNCMP(p, _T("&apos;"), 6) == 0) {
+                *q = '\'';
+                SKIP_CHARS(p, 6);
+            } else if (JPACKAGE_STRNCMP(p, _T("&quote;"), 7) == 0) {
+                *q = '\"';
+                SKIP_CHARS(p, 7);
+            } else {
+                *q++ = *p;
+                NEXT_CHAR(p);
+            }
+        }
+    }
+    *q = '\0';
+}
+
+/* ------------------------------------------------------------- */
+/* XML tokenizer */
+
+#define TOKEN_UNKNOWN             0
+#define TOKEN_BEGIN_TAG           1  /* <tag */
+#define TOKEN_END_TAG             2  /* </tag */
+#define TOKEN_CLOSE_BRACKET       3  /* >  */
+#define TOKEN_EMPTY_CLOSE_BRACKET 4  /* /> */
+#define TOKEN_PCDATA              5  /* pcdata */
+#define TOKEN_CDATA               6  /* cdata */
+#define TOKEN_EOF                 7
+
+static TCHAR* CurPos = NULL;
+static TCHAR* CurTokenName = NULL;
+static int CurTokenType;
+static int MaxTokenSize = -1;
+
+/* Copy token from buffer to Token variable */
+static void SetToken(int type, TCHAR* start, TCHAR* end) {
+    int len = end - start;
+    if (len > MaxTokenSize) {
+        if (CurTokenName != NULL) free(CurTokenName);
+        CurTokenName = (TCHAR *) malloc((len + 1) * sizeof (TCHAR));
+        if (CurTokenName == NULL) {
+            return;
+        }
+        MaxTokenSize = len;
+    }
+
+    CurTokenType = type;
+    JPACKAGE_STRNCPY(CurTokenName, len + 1, start, len);
+    CurTokenName[len] = '\0';
+}
+
+/* Skip XML comments, doctypes, and prolog tags */
+static TCHAR* SkipFilling(void) {
+    TCHAR *q = CurPos;
+
+    /* Skip white space and comment sections */
+    do {
+        q = CurPos;
+        CurPos = SkipWhiteSpace(CurPos);
+        CurPos = SkipXMLComment(CurPos); /* Must be called befor DocTypes */
+        CurPos = SkipXMLDocType(CurPos); /* <! ... > directives */
+        CurPos = SkipXMLProlog(CurPos); /* <? ... ?> directives */
+    } while (CurPos != q);
+
+    return CurPos;
+}
+
+/* Parses next token and initializes the global token variables above
+   The tokennizer automatically skips comments (<!-- comment -->) and
+   <! ... > directives.
+ */
+static void GetNextToken(void) {
+    TCHAR *p, *q;
+
+    /* Skip white space and comment sections */
+    p = SkipFilling();
+
+    if (p == NULL || *p == '\0') {
+        CurTokenType = TOKEN_EOF;
+        return;
+    } else if (p[0] == '<' && p[1] == '/') {
+        /* TOKEN_END_TAG */
+        q = SkipXMLName(p + 2);
+        SetToken(TOKEN_END_TAG, p + 2, q);
+        p = q;
+    } else if (*p == '<') {
+        /* TOKEN_BEGIN_TAG */
+        q = SkipXMLName(p + 1);
+        SetToken(TOKEN_BEGIN_TAG, p + 1, q);
+        p = q;
+    } else if (p[0] == '>') {
+        CurTokenType = TOKEN_CLOSE_BRACKET;
+        NEXT_CHAR(p);
+    } else if (p[0] == '/' && p[1] == '>') {
+        CurTokenType = TOKEN_EMPTY_CLOSE_BRACKET;
+        SKIP_CHARS(p, 2);
+    } else {
+        /* Search for end of data */
+        q = p + 1;
+        while (*q && *q != '<') {
+            if (IsPCData(q)) {
+                q = SkipPCData(q);
+            } else {
+                NEXT_CHAR(q);
+            }
+        }
+        SetToken(TOKEN_PCDATA, p, q);
+        /* Convert all entities inside token */
+        ConvertBuiltInEntities(CurTokenName);
+        p = q;
+    }
+    /* Advance pointer to beginning of next token */
+    CurPos = p;
+}
+
+static XMLNode* CreateXMLNode(int type, TCHAR* name) {
+    XMLNode* node;
+    node = (XMLNode*) malloc(sizeof (XMLNode));
+    if (node == NULL) {
+        return NULL;
+    }
+    node->_type = type;
+    node->_name = name;
+    node->_next = NULL;
+    node->_sub = NULL;
+    node->_attributes = NULL;
+    return node;
+}
+
+static XMLAttribute* CreateXMLAttribute(TCHAR *name, TCHAR* value) {
+    XMLAttribute* attr;
+    attr = (XMLAttribute*) malloc(sizeof (XMLAttribute));
+    if (attr == NULL) {
+        return NULL;
+    }
+    attr->_name = name;
+    attr->_value = value;
+    attr->_next = NULL;
+    return attr;
+}
+
+XMLNode* ParseXMLDocument(TCHAR* buf) {
+    XMLNode* root;
+    int err_code = setjmp(jmpbuf);
+    switch (err_code) {
+        case JMP_NO_ERROR:
+#ifndef _UNICODE
+            /* Remove UTF-8 encoding from buffer */
+            RemoveNonAsciiUTF8FromBuffer(buf);
+#endif
+
+            /* Get first Token */
+            CurPos = buf;
+            GetNextToken();
+
+            /* Parse document*/
+            root = ParseXMLElement();
+            break;
+        case JMP_OUT_OF_RANGE:
+            /* cleanup: */
+            if (root_node != NULL) {
+                FreeXMLDocument(root_node);
+                root_node = NULL;
+            }
+            if (CurTokenName != NULL) free(CurTokenName);
+            fprintf(stderr, "Error during parsing jnlp file...\n");
+            exit(-1);
+            break;
+        default:
+            root = NULL;
+            break;
+    }
+
+    return root;
+}
+
+static XMLNode* ParseXMLElement(void) {
+    XMLNode* node = NULL;
+    XMLNode* subnode = NULL;
+    XMLNode* nextnode = NULL;
+    XMLAttribute* attr = NULL;
+
+    if (CurTokenType == TOKEN_BEGIN_TAG) {
+
+        /* Create node for new element tag */
+        node = CreateXMLNode(xmlTagType, JPACKAGE_STRDUP(CurTokenName));
+        /* We need to save root node pointer to be able to cleanup
+           if an error happens during parsing */
+        if (!root_node) {
+            root_node = node;
+        }
+        /* Parse attributes. This section eats a all input until
+           EOF, a > or a /> */
+        attr = ParseXMLAttribute();
+        while (attr != NULL) {
+            attr->_next = node->_attributes;
+            node->_attributes = attr;
+            attr = ParseXMLAttribute();
+        }
+
+        /* This will eihter be a TOKEN_EOF, TOKEN_CLOSE_BRACKET, or a
+         * TOKEN_EMPTY_CLOSE_BRACKET */
+        GetNextToken();
+
+        if (CurTokenType == TOKEN_EMPTY_CLOSE_BRACKET) {
+            GetNextToken();
+            /* We are done with the sublevel - fall through to continue */
+            /* parsing tags at the same level */
+        } else if (CurTokenType == TOKEN_CLOSE_BRACKET) {
+            GetNextToken();
+
+            /* Parse until end tag if found */
+            node->_sub = ParseXMLElement();
+
+            if (CurTokenType == TOKEN_END_TAG) {
+                /* Find closing bracket '>' for end tag */
+                do {
+                    GetNextToken();
+                } while (CurTokenType != TOKEN_EOF &&
+                        CurTokenType != TOKEN_CLOSE_BRACKET);
+                GetNextToken();
+            }
+        }
+
+        /* Continue parsing rest on same level */
+        if (CurTokenType != TOKEN_EOF) {
+            /* Parse rest of stream at same level */
+            node->_next = ParseXMLElement();
+        }
+        return node;
+
+    } else if (CurTokenType == TOKEN_PCDATA) {
+        /* Create node for pcdata */
+        node = CreateXMLNode(xmlPCDataType, JPACKAGE_STRDUP(CurTokenName));
+        /* We need to save root node pointer to be able to cleanup
+           if an error happens during parsing */
+        if (!root_node) {
+            root_node = node;
+        }
+        GetNextToken();
+        return node;
+    }
+
+    /* Something went wrong. */
+    return NULL;
+}
+
+/* Parses an XML attribute. */
+static XMLAttribute* ParseXMLAttribute(void) {
+    TCHAR* q = NULL;
+    TCHAR* name = NULL;
+    TCHAR* PrevPos = NULL;
+
+    do {
+        /* We need to check this condition to avoid endless loop
+           in case if an error happend during parsing. */
+        if (PrevPos == CurPos) {
+            if (name != NULL) {
+                free(name);
+                name = NULL;
+            }
+
+            return NULL;
+        }
+
+        PrevPos = CurPos;
+
+        /* Skip whitespace etc. */
+        SkipFilling();
+
+        /* Check if we are done witht this attribute section */
+        if (CurPos[0] == '\0' ||
+                CurPos[0] == '>' ||
+                (CurPos[0] == '/' && CurPos[1] == '>')) {
+
+            if (name != NULL) {
+                free(name);
+                name = NULL;
+            }
+
+            return NULL;
+        }
+
+        /* Find end of name */
+        q = CurPos;
+        while (*q && !iswspace(*q) && *q != '=') NEXT_CHAR(q);
+
+        SetToken(TOKEN_UNKNOWN, CurPos, q);
+        if (name) {
+            free(name);
+            name = NULL;
+        }
+        name = JPACKAGE_STRDUP(CurTokenName);
+
+        /* Skip any whitespace */
+        CurPos = q;
+        CurPos = SkipFilling();
+
+        /* Next TCHARacter must be '=' for a valid attribute.
+           If it is not, this is really an error.
+           We ignore this, and just try to parse an attribute
+           out of the rest of the string.
+         */
+    } while (*CurPos != '=');
+
+    NEXT_CHAR(CurPos);
+    CurPos = SkipWhiteSpace(CurPos);
+    /* Parse CDATA part of attribute */
+    if ((*CurPos == '\"') || (*CurPos == '\'')) {
+        TCHAR quoteChar = *CurPos;
+        q = ++CurPos;
+        while (*q != '\0' && *q != quoteChar) NEXT_CHAR(q);
+        SetToken(TOKEN_CDATA, CurPos, q);
+        CurPos = q + 1;
+    } else {
+        q = CurPos;
+        while (*q != '\0' && !iswspace(*q)) NEXT_CHAR(q);
+        SetToken(TOKEN_CDATA, CurPos, q);
+        CurPos = q;
+    }
+
+    //Note: no need to free name and CurTokenName duplicate; they're assigned
+    // to an XMLAttribute structure in CreateXMLAttribute
+
+    return CreateXMLAttribute(name, JPACKAGE_STRDUP(CurTokenName));
+}
+
+void FreeXMLDocument(XMLNode* root) {
+    if (root == NULL) return;
+    FreeXMLDocument(root->_sub);
+    FreeXMLDocument(root->_next);
+    FreeXMLAttribute(root->_attributes);
+    free(root->_name);
+    free(root);
+}
+
+static void FreeXMLAttribute(XMLAttribute* attr) {
+    if (attr == NULL) return;
+    free(attr->_name);
+    free(attr->_value);
+    FreeXMLAttribute(attr->_next);
+    free(attr);
+}
+
+/* Find element at current level with a given name */
+XMLNode* FindXMLChild(XMLNode* root, const TCHAR* name) {
+    if (root == NULL) return NULL;
+
+    if (root->_type == xmlTagType && JPACKAGE_STRCMP(root->_name, name) == 0) {
+        return root;
+    }
+
+    return FindXMLChild(root->_next, name);
+}
+
+/* Search for an attribute with the given name and returns the contents.
+ * Returns NULL if attribute is not found
+ */
+TCHAR* FindXMLAttribute(XMLAttribute* attr, const TCHAR* name) {
+    if (attr == NULL) return NULL;
+    if (JPACKAGE_STRCMP(attr->_name, name) == 0) return attr->_value;
+    return FindXMLAttribute(attr->_next, name);
+}
+
+void PrintXMLDocument(XMLNode* node, int indt) {
+    if (node == NULL) return;
+
+    if (node->_type == xmlTagType) {
+        JPACKAGE_PRINTF(_T("\n"));
+        indent(indt);
+        JPACKAGE_PRINTF(_T("<%s"), node->_name);
+        PrintXMLAttributes(node->_attributes);
+        if (node->_sub == NULL) {
+            JPACKAGE_PRINTF(_T("/>\n"));
+        } else {
+            JPACKAGE_PRINTF(_T(">"));
+            PrintXMLDocument(node->_sub, indt + 1);
+            indent(indt);
+            JPACKAGE_PRINTF(_T("</%s>"), node->_name);
+        }
+    } else {
+        JPACKAGE_PRINTF(_T("%s"), node->_name);
+    }
+    PrintXMLDocument(node->_next, indt);
+}
+
+static void PrintXMLAttributes(XMLAttribute* attr) {
+    if (attr == NULL) return;
+
+    JPACKAGE_PRINTF(_T(" %s=\"%s\""), attr->_name, attr->_value);
+    PrintXMLAttributes(attr->_next);
+}
+
+static void indent(int indt) {
+    int i;
+    for (i = 0; i < indt; i++) {
+        JPACKAGE_PRINTF(_T("  "));
+    }
+}
+
+const TCHAR *CDStart = _T("<![CDATA[");
+const TCHAR *CDEnd = _T("]]>");
+
+static TCHAR* SkipPCData(TCHAR *p) {
+    TCHAR *end = JPACKAGE_STRSTR(p, CDEnd);
+    if (end != NULL) {
+        return end + sizeof (CDEnd);
+    }
+    return (++p);
+}
+
+static int IsPCData(TCHAR *p) {
+    const int size = sizeof (CDStart);
+    return (JPACKAGE_STRNCMP(CDStart, p, size) == 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/native/libapplauncher/LinuxPlatform.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef LINUXPLATFORM_H
+#define LINUXPLATFORM_H
+
+#include "Platform.h"
+#include "PosixPlatform.h"
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <pthread.h>
+#include <list>
+
+class LinuxPlatform : virtual public Platform, PosixPlatform {
+private:
+    pthread_t FMainThread;
+
+protected:
+    virtual TString getTmpDirString();
+
+public:
+    LinuxPlatform(void);
+    virtual ~LinuxPlatform(void);
+
+    TString GetPackageAppDirectory();
+    TString GetPackageLauncherDirectory();
+    TString GetPackageRuntimeBinDirectory();
+
+    virtual void ShowMessage(TString title, TString description);
+    virtual void ShowMessage(TString description);
+
+    virtual TCHAR* ConvertStringToFileSystemString(
+            TCHAR* Source, bool &release);
+    virtual TCHAR* ConvertFileSystemStringToString(
+            TCHAR* Source, bool &release);
+
+    virtual TString GetPackageRootDirectory();
+    virtual TString GetAppDataDirectory();
+    virtual TString GetAppName();
+
+    virtual TString GetModuleFileName();
+
+    virtual TString GetBundledJavaLibraryFileName(TString RuntimePath);
+
+    virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
+
+    virtual bool IsMainThread();
+    virtual TPlatformNumber GetMemorySize();
+};
+
+#endif //LINUXPLATFORM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/linux/native/libapplauncher/PlatformDefs.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef PLATFORM_DEFS_H
+#define PLATFORM_DEFS_H
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <libgen.h>
+#include <string>
+
+using namespace std;
+
+#ifndef LINUX
+#define LINUX
+#endif
+
+#define _T(x) x
+
+typedef char TCHAR;
+typedef std::string TString;
+#define StringLength strlen
+
+typedef unsigned long DWORD;
+
+#define TRAILING_PATHSEPARATOR '/'
+#define BAD_TRAILING_PATHSEPARATOR '\\'
+#define PATH_SEPARATOR ':'
+#define BAD_PATH_SEPARATOR ';'
+#define MAX_PATH 1000
+
+typedef long TPlatformNumber;
+typedef pid_t TProcessID;
+
+#define HMODULE void*
+
+typedef void* Module;
+typedef void* Procedure;
+
+#define StringToFileSystemString PlatformString
+#define FileSystemStringToString PlatformString
+
+#endif // PLATFORM_DEFS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/EnumeratedBundlerParam.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * EnumeratedBundlerParams<T>
+ *
+ * Contains key-value pairs (elements) where keys are "displayable"
+ * keys which the IDE can display/choose and values are "identifier" values
+ * which can be stored in parameters' map.
+ *
+ * For instance the Mac has a predefined set of categories which can be applied
+ * to LSApplicationCategoryType which is required for the mac app store.
+ *
+ * The following example illustrates a simple usage of
+ *     the MAC_CATEGORY parameter:
+ *
+ * <pre>{@code
+ *     Set<String> keys = MAC_CATEGORY.getDisplayableKeys();
+ *
+ *     String key = getLastValue(keys); // get last value for example
+ *
+ *     String value = MAC_CATEGORY.getValueForDisplayableKey(key);
+ *     params.put(MAC_CATEGORY.getID(), value);
+ * }</pre>
+ *
+ */
+class EnumeratedBundlerParam<T> extends BundlerParamInfo<T> {
+    // Not sure if this is the correct order, my idea is that from IDE
+    // perspective the string to display to the user is the key and then the
+    // value is some type of object (although probably a String in most cases)
+    private final Map<String, T> elements;
+    private final boolean strict;
+
+    EnumeratedBundlerParam(String id, Class<T> valueType,
+            Function<Map<String, ? super Object>, T> defaultValueFunction,
+            BiFunction<String, Map<String, ? super Object>, T> stringConverter,
+            Map<String, T> elements, boolean strict) {
+        this.id = id;
+        this.valueType = valueType;
+        this.defaultValueFunction = defaultValueFunction;
+        this.stringConverter = stringConverter;
+        this.elements = elements;
+        this.strict = strict;
+    }
+
+    boolean isInPossibleValues(T value) {
+        return elements.values().contains(value);
+    }
+
+    // Having the displayable values as the keys seems a bit wacky
+    Set<String> getDisplayableKeys() {
+        return Collections.unmodifiableSet(elements.keySet());
+    }
+
+    // mapping from a "displayable" key to an "identifier" value.
+    T getValueForDisplayableKey(String displayableKey) {
+        return elements.get(displayableKey);
+    }
+
+    boolean isStrict() {
+        return strict;
+    }
+
+    boolean isLoose() {
+        return !isStrict();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ResourceBundle;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+import static jdk.incubator.jpackage.internal.MacBaseInstallerBundler.*;
+
+public class MacAppBundler extends AbstractImageBundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MacResources");
+
+    private static final String TEMPLATE_BUNDLE_ICON = "java.icns";
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.MAC_BUNDLE_NAME.getId(),
+                    String.class,
+                    params -> null,
+                    (s, p) -> s);
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION =
+            new StandardBundlerParam<>(
+                    "mac.CFBundleVersion",
+                    String.class,
+                    p -> {
+                        String s = VERSION.fetchFrom(p);
+                        if (validCFBundleVersion(s)) {
+                            return s;
+                        } else {
+                            return "100";
+                        }
+                    },
+                    (s, p) -> s);
+
+    public static final BundlerParamInfo<String> DEFAULT_ICNS_ICON =
+            new StandardBundlerParam<>(
+            ".mac.default.icns",
+            String.class,
+            params -> TEMPLATE_BUNDLE_ICON,
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<String> DEVELOPER_ID_APP_SIGNING_KEY =
+            new StandardBundlerParam<>(
+            "mac.signing-key-developer-id-app",
+            String.class,
+            params -> {
+                    String result = MacBaseInstallerBundler.findKey(
+                            "Developer ID Application: "
+                            + SIGNING_KEY_USER.fetchFrom(params),
+                            SIGNING_KEYCHAIN.fetchFrom(params),
+                            VERBOSE.fetchFrom(params));
+                    if (result != null) {
+                        MacCertificate certificate = new MacCertificate(result);
+
+                        if (!certificate.isValid()) {
+                            Log.error(MessageFormat.format(I18N.getString(
+                                    "error.certificate.expired"), result));
+                        }
+                    }
+
+                    return result;
+                },
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<String> BUNDLE_ID_SIGNING_PREFIX =
+            new StandardBundlerParam<>(
+            Arguments.CLIOptions.MAC_BUNDLE_SIGNING_PREFIX.getId(),
+            String.class,
+            params -> IDENTIFIER.fetchFrom(params) + ".",
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<File> ICON_ICNS =
+            new StandardBundlerParam<>(
+            "icon.icns",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".icns")) {
+                    Log.error(MessageFormat.format(
+                            I18N.getString("message.icon-not-icns"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+    public static boolean validCFBundleVersion(String v) {
+        // CFBundleVersion (String - iOS, OS X) specifies the build version
+        // number of the bundle, which identifies an iteration (released or
+        // unreleased) of the bundle. The build version number should be a
+        // string comprised of three non-negative, period-separated integers
+        // with the first integer being greater than zero. The string should
+        // only contain numeric (0-9) and period (.) characters. Leading zeros
+        // are truncated from each integer and will be ignored (that is,
+        // 1.02.3 is equivalent to 1.2.3). This key is not localizable.
+
+        if (v == null) {
+            return false;
+        }
+
+        String p[] = v.split("\\.");
+        if (p.length > 3 || p.length < 1) {
+            Log.verbose(I18N.getString(
+                    "message.version-string-too-many-components"));
+            return false;
+        }
+
+        try {
+            BigInteger n = new BigInteger(p[0]);
+            if (BigInteger.ONE.compareTo(n) > 0) {
+                Log.verbose(I18N.getString(
+                        "message.version-string-first-number-not-zero"));
+                return false;
+            }
+            if (p.length > 1) {
+                n = new BigInteger(p[1]);
+                if (BigInteger.ZERO.compareTo(n) > 0) {
+                    Log.verbose(I18N.getString(
+                            "message.version-string-no-negative-numbers"));
+                    return false;
+                }
+            }
+            if (p.length > 2) {
+                n = new BigInteger(p[2]);
+                if (BigInteger.ZERO.compareTo(n) > 0) {
+                    Log.verbose(I18N.getString(
+                            "message.version-string-no-negative-numbers"));
+                    return false;
+                }
+            }
+        } catch (NumberFormatException ne) {
+            Log.verbose(I18N.getString("message.version-string-numbers-only"));
+            Log.verbose(ne);
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws ConfigException {
+        try {
+            return doValidate(params);
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    private boolean doValidate(Map<String, ? super Object> params)
+            throws ConfigException {
+
+        imageBundleValidation(params);
+
+        if (StandardBundlerParam.getPredefinedAppImage(params) != null) {
+            return true;
+        }
+
+        // validate short version
+        if (!validCFBundleVersion(MAC_CF_BUNDLE_VERSION.fetchFrom(params))) {
+            throw new ConfigException(
+                    I18N.getString("error.invalid-cfbundle-version"),
+                    I18N.getString("error.invalid-cfbundle-version.advice"));
+        }
+
+        // reject explicitly set sign to true and no valid signature key
+        if (Optional.ofNullable(MacAppImageBuilder.
+                    SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) {
+            String signingIdentity =
+                    DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
+            if (signingIdentity == null) {
+                throw new ConfigException(
+                        I18N.getString("error.explicit-sign-no-cert"),
+                        I18N.getString("error.explicit-sign-no-cert.advice"));
+            }
+
+            // Signing will not work without Xcode with command line developer tools
+            try {
+                ProcessBuilder pb = new ProcessBuilder("xcrun", "--help");
+                Process p = pb.start();
+                int code = p.waitFor();
+                if (code != 0) {
+                    throw new ConfigException(
+                        I18N.getString("error.no.xcode.signing"),
+                        I18N.getString("error.no.xcode.signing.advice"));
+                }
+            } catch (IOException | InterruptedException ex) {
+                throw new ConfigException(ex);
+            }
+        }
+
+        return true;
+    }
+
+    File doBundle(Map<String, ? super Object> params, File outputDirectory,
+            boolean dependentTask) throws PackagerException {
+        if (StandardBundlerParam.isRuntimeInstaller(params)) {
+            return PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
+        } else {
+            return doAppBundle(params, outputDirectory, dependentTask);
+        }
+    }
+
+    File doAppBundle(Map<String, ? super Object> params, File outputDirectory,
+            boolean dependentTask) throws PackagerException {
+        try {
+            File rootDirectory = createRoot(params, outputDirectory,
+                    dependentTask, APP_NAME.fetchFrom(params) + ".app");
+            AbstractAppImageBuilder appBuilder =
+                    new MacAppImageBuilder(params, outputDirectory.toPath());
+            if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(params) == null ) {
+                JLinkBundlerHelper.execute(params, appBuilder);
+            } else {
+                StandardBundlerParam.copyPredefinedRuntimeImage(
+                        params, appBuilder);
+            }
+            return rootDirectory;
+        } catch (PackagerException pe) {
+            throw pe;
+        } catch (Exception ex) {
+            Log.verbose(ex);
+            throw new PackagerException(ex);
+        }
+    }
+
+    /////////////////////////////////////////////////////////////////////////
+    // Implement Bundler
+    /////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String getName() {
+        return I18N.getString("app.bundler.name");
+    }
+
+    @Override
+    public String getID() {
+        return "mac.app";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "IMAGE";
+    }
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) throws PackagerException {
+        return doBundle(params, outputParentDir, false);
+    }
+
+    @Override
+    public boolean supported(boolean runtimeInstaller) {
+        return true;
+    }
+
+    @Override
+    public boolean isDefault() {
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,945 @@
+/*
+ * Copyright (c) 2015, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.math.BigInteger;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.PosixFilePermission;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+import static jdk.incubator.jpackage.internal.MacBaseInstallerBundler.*;
+import static jdk.incubator.jpackage.internal.MacAppBundler.*;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+
+public class MacAppImageBuilder extends AbstractAppImageBuilder {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MacResources");
+
+    private static final String LIBRARY_NAME = "libapplauncher.dylib";
+    private static final String TEMPLATE_BUNDLE_ICON = "java.icns";
+    private static final String OS_TYPE_CODE = "APPL";
+    private static final String TEMPLATE_INFO_PLIST_LITE =
+            "Info-lite.plist.template";
+    private static final String TEMPLATE_RUNTIME_INFO_PLIST =
+            "Runtime-Info.plist.template";
+
+    private final Path root;
+    private final Path contentsDir;
+    private final Path appDir;
+    private final Path javaModsDir;
+    private final Path resourcesDir;
+    private final Path macOSDir;
+    private final Path runtimeDir;
+    private final Path runtimeRoot;
+    private final Path mdir;
+
+    private static List<String> keyChains;
+
+    public static final BundlerParamInfo<Boolean>
+            MAC_CONFIGURE_LAUNCHER_IN_PLIST = new StandardBundlerParam<>(
+                    "mac.configure-launcher-in-plist",
+                    Boolean.class,
+                    params -> Boolean.FALSE,
+                    (s, p) -> Boolean.valueOf(s));
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.MAC_BUNDLE_NAME.getId(),
+                    String.class,
+                    params -> null,
+                    (s, p) -> s);
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_IDENTIFIER =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(),
+                    String.class,
+                    params -> {
+                        // Get identifier from app image if user provided
+                        // app image and did not provide the identifier via CLI.
+                        String identifier = extractBundleIdentifier(params);
+                        if (identifier != null) {
+                            return identifier;
+                        }
+
+                        return IDENTIFIER.fetchFrom(params);
+                    },
+                    (s, p) -> s);
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION =
+            new StandardBundlerParam<>(
+                    "mac.CFBundleVersion",
+                    String.class,
+                    p -> {
+                        String s = VERSION.fetchFrom(p);
+                        if (validCFBundleVersion(s)) {
+                            return s;
+                        } else {
+                            return "100";
+                        }
+                    },
+                    (s, p) -> s);
+
+    public static final BundlerParamInfo<File> ICON_ICNS =
+            new StandardBundlerParam<>(
+            "icon.icns",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".icns")) {
+                    Log.error(MessageFormat.format(
+                            I18N.getString("message.icon-not-icns"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+    public static final StandardBundlerParam<Boolean> SIGN_BUNDLE  =
+            new StandardBundlerParam<>(
+            Arguments.CLIOptions.MAC_SIGN.getId(),
+            Boolean.class,
+            params -> false,
+            // valueOf(null) is false, we actually do want null in some cases
+            (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
+                    null : Boolean.valueOf(s)
+        );
+
+    public MacAppImageBuilder(Map<String, Object> params, Path imageOutDir)
+            throws IOException {
+        super(params, imageOutDir.resolve(APP_NAME.fetchFrom(params)
+                + ".app/Contents/runtime/Contents/Home"));
+
+        Objects.requireNonNull(imageOutDir);
+
+        this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params) + ".app");
+        this.contentsDir = root.resolve("Contents");
+        this.appDir = contentsDir.resolve("app");
+        this.javaModsDir = appDir.resolve("mods");
+        this.resourcesDir = contentsDir.resolve("Resources");
+        this.macOSDir = contentsDir.resolve("MacOS");
+        this.runtimeDir = contentsDir.resolve("runtime");
+        this.runtimeRoot = runtimeDir.resolve("Contents/Home");
+        this.mdir = runtimeRoot.resolve("lib");
+        Files.createDirectories(appDir);
+        Files.createDirectories(resourcesDir);
+        Files.createDirectories(macOSDir);
+        Files.createDirectories(runtimeDir);
+    }
+
+    private void writeEntry(InputStream in, Path dstFile) throws IOException {
+        Files.createDirectories(dstFile.getParent());
+        Files.copy(in, dstFile);
+    }
+
+    public static boolean validCFBundleVersion(String v) {
+        // CFBundleVersion (String - iOS, OS X) specifies the build version
+        // number of the bundle, which identifies an iteration (released or
+        // unreleased) of the bundle. The build version number should be a
+        // string comprised of three non-negative, period-separated integers
+        // with the first integer being greater than zero. The string should
+        // only contain numeric (0-9) and period (.) characters. Leading zeros
+        // are truncated from each integer and will be ignored (that is,
+        // 1.02.3 is equivalent to 1.2.3). This key is not localizable.
+
+        if (v == null) {
+            return false;
+        }
+
+        String p[] = v.split("\\.");
+        if (p.length > 3 || p.length < 1) {
+            Log.verbose(I18N.getString(
+                    "message.version-string-too-many-components"));
+            return false;
+        }
+
+        try {
+            BigInteger n = new BigInteger(p[0]);
+            if (BigInteger.ONE.compareTo(n) > 0) {
+                Log.verbose(I18N.getString(
+                        "message.version-string-first-number-not-zero"));
+                return false;
+            }
+            if (p.length > 1) {
+                n = new BigInteger(p[1]);
+                if (BigInteger.ZERO.compareTo(n) > 0) {
+                    Log.verbose(I18N.getString(
+                            "message.version-string-no-negative-numbers"));
+                    return false;
+                }
+            }
+            if (p.length > 2) {
+                n = new BigInteger(p[2]);
+                if (BigInteger.ZERO.compareTo(n) > 0) {
+                    Log.verbose(I18N.getString(
+                            "message.version-string-no-negative-numbers"));
+                    return false;
+                }
+            }
+        } catch (NumberFormatException ne) {
+            Log.verbose(I18N.getString("message.version-string-numbers-only"));
+            Log.verbose(ne);
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public Path getAppDir() {
+        return appDir;
+    }
+
+    @Override
+    public Path getAppModsDir() {
+        return javaModsDir;
+    }
+
+    @Override
+    public void prepareApplicationFiles(Map<String, ? super Object> params)
+            throws IOException {
+        Map<String, ? super Object> originalParams = new HashMap<>(params);
+        // Generate PkgInfo
+        File pkgInfoFile = new File(contentsDir.toFile(), "PkgInfo");
+        pkgInfoFile.createNewFile();
+        writePkgInfo(pkgInfoFile);
+
+        Path executable = macOSDir.resolve(getLauncherName(params));
+
+        // create the main app launcher
+        try (InputStream is_launcher =
+                getResourceAsStream("jpackageapplauncher");
+            InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
+            // Copy executable and library to MacOS folder
+            writeEntry(is_launcher, executable);
+            writeEntry(is_lib, macOSDir.resolve(LIBRARY_NAME));
+        }
+        executable.toFile().setExecutable(true, false);
+        // generate main app launcher config file
+        File cfg = new File(root.toFile(), getLauncherCfgName(params));
+        writeCfgFile(params, cfg);
+
+        // create additional app launcher(s) and config file(s)
+        List<Map<String, ? super Object>> entryPoints =
+                StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
+        for (Map<String, ? super Object> entryPoint : entryPoints) {
+            Map<String, ? super Object> tmp =
+                    AddLauncherArguments.merge(originalParams, entryPoint);
+
+            // add executable for add launcher
+            Path addExecutable = macOSDir.resolve(getLauncherName(tmp));
+            try (InputStream is = getResourceAsStream("jpackageapplauncher");) {
+                writeEntry(is, addExecutable);
+            }
+            addExecutable.toFile().setExecutable(true, false);
+
+            // add config file for add launcher
+            cfg = new File(root.toFile(), getLauncherCfgName(tmp));
+            writeCfgFile(tmp, cfg);
+        }
+
+        // Copy class path entries to Java folder
+        copyClassPathEntries(appDir, params);
+
+        /*********** Take care of "config" files *******/
+
+        createResource(TEMPLATE_BUNDLE_ICON, params)
+                .setCategory("icon")
+                .setExternal(ICON_ICNS.fetchFrom(params))
+                .saveToFile(resourcesDir.resolve(APP_NAME.fetchFrom(params)
+                        + ".icns"));
+
+        // copy file association icons
+        for (Map<String, ?
+                super Object> fa : FILE_ASSOCIATIONS.fetchFrom(params)) {
+            File f = FA_ICON.fetchFrom(fa);
+            if (f != null && f.exists()) {
+                try (InputStream in2 = new FileInputStream(f)) {
+                    Files.copy(in2, resourcesDir.resolve(f.getName()));
+                }
+
+            }
+        }
+
+        copyRuntimeFiles(params);
+        sign(params);
+    }
+
+    @Override
+    public void prepareJreFiles(Map<String, ? super Object> params)
+            throws IOException {
+        copyRuntimeFiles(params);
+        sign(params);
+    }
+
+    @Override
+    File getRuntimeImageDir(File runtimeImageTop) {
+        File home = new File(runtimeImageTop, "Contents/Home");
+        return (home.exists() ? home : runtimeImageTop);
+    }
+
+    private void copyRuntimeFiles(Map<String, ? super Object> params)
+            throws IOException {
+        // Generate Info.plist
+        writeInfoPlist(contentsDir.resolve("Info.plist").toFile(), params);
+
+        // generate java runtime info.plist
+        writeRuntimeInfoPlist(
+                runtimeDir.resolve("Contents/Info.plist").toFile(), params);
+
+        // copy library
+        Path runtimeMacOSDir = Files.createDirectories(
+                runtimeDir.resolve("Contents/MacOS"));
+
+        // JDK 9, 10, and 11 have extra '/jli/' subdir
+        Path jli = runtimeRoot.resolve("lib/libjli.dylib");
+        if (!Files.exists(jli)) {
+            jli = runtimeRoot.resolve("lib/jli/libjli.dylib");
+        }
+
+        Files.copy(jli, runtimeMacOSDir.resolve("libjli.dylib"));
+    }
+
+    private void sign(Map<String, ? super Object> params) throws IOException {
+        if (Optional.ofNullable(
+                SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) {
+            try {
+                addNewKeychain(params);
+            } catch (InterruptedException e) {
+                Log.error(e.getMessage());
+            }
+            String signingIdentity =
+                    DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
+            if (signingIdentity != null) {
+                signAppBundle(params, root, signingIdentity,
+                        BUNDLE_ID_SIGNING_PREFIX.fetchFrom(params), null, null);
+            }
+            restoreKeychainList(params);
+        }
+    }
+
+    private String getLauncherName(Map<String, ? super Object> params) {
+        if (APP_NAME.fetchFrom(params) != null) {
+            return APP_NAME.fetchFrom(params);
+        } else {
+            return MAIN_CLASS.fetchFrom(params);
+        }
+    }
+
+    public static String getLauncherCfgName(
+            Map<String, ? super Object> params) {
+        return "Contents/app/" + APP_NAME.fetchFrom(params) + ".cfg";
+    }
+
+    private void copyClassPathEntries(Path javaDirectory,
+            Map<String, ? super Object> params) throws IOException {
+        List<RelativeFileSet> resourcesList =
+                APP_RESOURCES_LIST.fetchFrom(params);
+        if (resourcesList == null) {
+            throw new RuntimeException(
+                    I18N.getString("message.null-classpath"));
+        }
+
+        for (RelativeFileSet classPath : resourcesList) {
+            File srcdir = classPath.getBaseDirectory();
+            for (String fname : classPath.getIncludedFiles()) {
+                copyEntry(javaDirectory, srcdir, fname);
+            }
+        }
+    }
+
+    private String getBundleName(Map<String, ? super Object> params) {
+        if (MAC_CF_BUNDLE_NAME.fetchFrom(params) != null) {
+            String bn = MAC_CF_BUNDLE_NAME.fetchFrom(params);
+            if (bn.length() > 16) {
+                Log.error(MessageFormat.format(I18N.getString(
+                        "message.bundle-name-too-long-warning"),
+                        MAC_CF_BUNDLE_NAME.getID(), bn));
+            }
+            return MAC_CF_BUNDLE_NAME.fetchFrom(params);
+        } else if (APP_NAME.fetchFrom(params) != null) {
+            return APP_NAME.fetchFrom(params);
+        } else {
+            String nm = MAIN_CLASS.fetchFrom(params);
+            if (nm.length() > 16) {
+                nm = nm.substring(0, 16);
+            }
+            return nm;
+        }
+    }
+
+    private void writeRuntimeInfoPlist(File file,
+            Map<String, ? super Object> params) throws IOException {
+        Map<String, String> data = new HashMap<>();
+        String identifier = StandardBundlerParam.isRuntimeInstaller(params) ?
+                MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) :
+                "com.oracle.java." + MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params);
+        data.put("CF_BUNDLE_IDENTIFIER", identifier);
+        String name = StandardBundlerParam.isRuntimeInstaller(params) ?
+                getBundleName(params): "Java Runtime Image";
+        data.put("CF_BUNDLE_NAME", name);
+        data.put("CF_BUNDLE_VERSION", VERSION.fetchFrom(params));
+        data.put("CF_BUNDLE_SHORT_VERSION_STRING", VERSION.fetchFrom(params));
+
+        createResource(TEMPLATE_RUNTIME_INFO_PLIST, params)
+                .setPublicName("Runtime-Info.plist")
+                .setCategory(I18N.getString("resource.runtime-info-plist"))
+                .setSubstitutionData(data)
+                .saveToFile(file);
+    }
+
+    private void writeInfoPlist(File file, Map<String, ? super Object> params)
+            throws IOException {
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.preparing-info-plist"), file.getAbsolutePath()));
+
+        //prepare config for exe
+        //Note: do not need CFBundleDisplayName if we don't support localization
+        Map<String, String> data = new HashMap<>();
+        data.put("DEPLOY_ICON_FILE", APP_NAME.fetchFrom(params) + ".icns");
+        data.put("DEPLOY_BUNDLE_IDENTIFIER",
+                MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params));
+        data.put("DEPLOY_BUNDLE_NAME",
+                getBundleName(params));
+        data.put("DEPLOY_BUNDLE_COPYRIGHT",
+                COPYRIGHT.fetchFrom(params) != null ?
+                COPYRIGHT.fetchFrom(params) : "Unknown");
+        data.put("DEPLOY_LAUNCHER_NAME", getLauncherName(params));
+        data.put("DEPLOY_BUNDLE_SHORT_VERSION",
+                VERSION.fetchFrom(params) != null ?
+                VERSION.fetchFrom(params) : "1.0.0");
+        data.put("DEPLOY_BUNDLE_CFBUNDLE_VERSION",
+                MAC_CF_BUNDLE_VERSION.fetchFrom(params) != null ?
+                MAC_CF_BUNDLE_VERSION.fetchFrom(params) : "100");
+
+        boolean hasMainJar = MAIN_JAR.fetchFrom(params) != null;
+        boolean hasMainModule =
+                StandardBundlerParam.MODULE.fetchFrom(params) != null;
+
+        if (hasMainJar) {
+            data.put("DEPLOY_MAIN_JAR_NAME", MAIN_JAR.fetchFrom(params).
+                    getIncludedFiles().iterator().next());
+        }
+        else if (hasMainModule) {
+            data.put("DEPLOY_MODULE_NAME",
+                    StandardBundlerParam.MODULE.fetchFrom(params));
+        }
+
+        StringBuilder sb = new StringBuilder();
+        List<String> jvmOptions = JAVA_OPTIONS.fetchFrom(params);
+
+        String newline = ""; //So we don't add extra line after last append
+        for (String o : jvmOptions) {
+            sb.append(newline).append(
+                    "    <string>").append(o).append("</string>");
+            newline = "\n";
+        }
+
+        data.put("DEPLOY_JAVA_OPTIONS", sb.toString());
+
+        sb = new StringBuilder();
+        List<String> args = ARGUMENTS.fetchFrom(params);
+        newline = "";
+        // So we don't add unneccessary extra line after last append
+
+        for (String o : args) {
+            sb.append(newline).append("    <string>").append(o).append(
+                    "</string>");
+            newline = "\n";
+        }
+        data.put("DEPLOY_ARGUMENTS", sb.toString());
+
+        newline = "";
+
+        data.put("DEPLOY_LAUNCHER_CLASS", MAIN_CLASS.fetchFrom(params));
+
+        data.put("DEPLOY_APP_CLASSPATH",
+                  getCfgClassPath(CLASSPATH.fetchFrom(params)));
+
+        StringBuilder bundleDocumentTypes = new StringBuilder();
+        StringBuilder exportedTypes = new StringBuilder();
+        for (Map<String, ? super Object>
+                fileAssociation : FILE_ASSOCIATIONS.fetchFrom(params)) {
+
+            List<String> extensions = FA_EXTENSIONS.fetchFrom(fileAssociation);
+
+            if (extensions == null) {
+                Log.verbose(I18N.getString(
+                        "message.creating-association-with-null-extension"));
+            }
+
+            List<String> mimeTypes = FA_CONTENT_TYPE.fetchFrom(fileAssociation);
+            String itemContentType = MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params)
+                    + "." + ((extensions == null || extensions.isEmpty())
+                    ? "mime" : extensions.get(0));
+            String description = FA_DESCRIPTION.fetchFrom(fileAssociation);
+            File icon = FA_ICON.fetchFrom(fileAssociation);
+
+            bundleDocumentTypes.append("    <dict>\n")
+                    .append("      <key>LSItemContentTypes</key>\n")
+                    .append("      <array>\n")
+                    .append("        <string>")
+                    .append(itemContentType)
+                    .append("</string>\n")
+                    .append("      </array>\n")
+                    .append("\n")
+                    .append("      <key>CFBundleTypeName</key>\n")
+                    .append("      <string>")
+                    .append(description)
+                    .append("</string>\n")
+                    .append("\n")
+                    .append("      <key>LSHandlerRank</key>\n")
+                    .append("      <string>Owner</string>\n")
+                            // TODO make a bundler arg
+                    .append("\n")
+                    .append("      <key>CFBundleTypeRole</key>\n")
+                    .append("      <string>Editor</string>\n")
+                            // TODO make a bundler arg
+                    .append("\n")
+                    .append("      <key>LSIsAppleDefaultForType</key>\n")
+                    .append("      <true/>\n")
+                            // TODO make a bundler arg
+                    .append("\n");
+
+            if (icon != null && icon.exists()) {
+                bundleDocumentTypes
+                        .append("      <key>CFBundleTypeIconFile</key>\n")
+                        .append("      <string>")
+                        .append(icon.getName())
+                        .append("</string>\n");
+            }
+            bundleDocumentTypes.append("    </dict>\n");
+
+            exportedTypes.append("    <dict>\n")
+                    .append("      <key>UTTypeIdentifier</key>\n")
+                    .append("      <string>")
+                    .append(itemContentType)
+                    .append("</string>\n")
+                    .append("\n")
+                    .append("      <key>UTTypeDescription</key>\n")
+                    .append("      <string>")
+                    .append(description)
+                    .append("</string>\n")
+                    .append("      <key>UTTypeConformsTo</key>\n")
+                    .append("      <array>\n")
+                    .append("          <string>public.data</string>\n")
+                            //TODO expose this?
+                    .append("      </array>\n")
+                    .append("\n");
+
+            if (icon != null && icon.exists()) {
+                exportedTypes.append("      <key>UTTypeIconFile</key>\n")
+                        .append("      <string>")
+                        .append(icon.getName())
+                        .append("</string>\n")
+                        .append("\n");
+            }
+
+            exportedTypes.append("\n")
+                    .append("      <key>UTTypeTagSpecification</key>\n")
+                    .append("      <dict>\n")
+                            // TODO expose via param? .append(
+                            // "        <key>com.apple.ostype</key>\n");
+                            // TODO expose via param? .append(
+                            // "        <string>ABCD</string>\n")
+                    .append("\n");
+
+            if (extensions != null && !extensions.isEmpty()) {
+                exportedTypes.append(
+                        "        <key>public.filename-extension</key>\n")
+                        .append("        <array>\n");
+
+                for (String ext : extensions) {
+                    exportedTypes.append("          <string>")
+                            .append(ext)
+                            .append("</string>\n");
+                }
+                exportedTypes.append("        </array>\n");
+            }
+            if (mimeTypes != null && !mimeTypes.isEmpty()) {
+                exportedTypes.append("        <key>public.mime-type</key>\n")
+                        .append("        <array>\n");
+
+                for (String mime : mimeTypes) {
+                    exportedTypes.append("          <string>")
+                            .append(mime)
+                            .append("</string>\n");
+                }
+                exportedTypes.append("        </array>\n");
+            }
+            exportedTypes.append("      </dict>\n")
+                    .append("    </dict>\n");
+        }
+        String associationData;
+        if (bundleDocumentTypes.length() > 0) {
+            associationData =
+                    "\n  <key>CFBundleDocumentTypes</key>\n  <array>\n"
+                    + bundleDocumentTypes.toString()
+                    + "  </array>\n\n"
+                    + "  <key>UTExportedTypeDeclarations</key>\n  <array>\n"
+                    + exportedTypes.toString()
+                    + "  </array>\n";
+        } else {
+            associationData = "";
+        }
+        data.put("DEPLOY_FILE_ASSOCIATIONS", associationData);
+
+        createResource(TEMPLATE_INFO_PLIST_LITE, params)
+                .setCategory(I18N.getString("resource.app-info-plist"))
+                .setSubstitutionData(data)
+                .setPublicName("Info.plist")
+                .saveToFile(file);
+    }
+
+    private void writePkgInfo(File file) throws IOException {
+        //hardcoded as it does not seem we need to change it ever
+        String signature = "????";
+
+        try (Writer out = Files.newBufferedWriter(file.toPath())) {
+            out.write(OS_TYPE_CODE + signature);
+            out.flush();
+        }
+    }
+
+    public static void addNewKeychain(Map<String, ? super Object> params)
+                                    throws IOException, InterruptedException {
+        if (Platform.getMajorVersion() < 10 ||
+                (Platform.getMajorVersion() == 10 &&
+                Platform.getMinorVersion() < 12)) {
+            // we need this for OS X 10.12+
+            return;
+        }
+
+        String keyChain = SIGNING_KEYCHAIN.fetchFrom(params);
+        if (keyChain == null || keyChain.isEmpty()) {
+            return;
+        }
+
+        // get current keychain list
+        String keyChainPath = new File (keyChain).getAbsolutePath().toString();
+        List<String> keychainList = new ArrayList<>();
+        int ret = IOUtils.getProcessOutput(
+                keychainList, "security", "list-keychains");
+        if (ret != 0) {
+            Log.error(I18N.getString("message.keychain.error"));
+            return;
+        }
+
+        boolean contains = keychainList.stream().anyMatch(
+                    str -> str.trim().equals("\""+keyChainPath.trim()+"\""));
+        if (contains) {
+            // keychain is already added in the search list
+            return;
+        }
+
+        keyChains = new ArrayList<>();
+        // remove "
+        keychainList.forEach((String s) -> {
+            String path = s.trim();
+            if (path.startsWith("\"") && path.endsWith("\"")) {
+                path = path.substring(1, path.length()-1);
+            }
+            keyChains.add(path);
+        });
+
+        List<String> args = new ArrayList<>();
+        args.add("security");
+        args.add("list-keychains");
+        args.add("-s");
+
+        args.addAll(keyChains);
+        args.add(keyChain);
+
+        ProcessBuilder  pb = new ProcessBuilder(args);
+        IOUtils.exec(pb);
+    }
+
+    public static void restoreKeychainList(Map<String, ? super Object> params)
+            throws IOException{
+        if (Platform.getMajorVersion() < 10 ||
+                (Platform.getMajorVersion() == 10 &&
+                Platform.getMinorVersion() < 12)) {
+            // we need this for OS X 10.12+
+            return;
+        }
+
+        if (keyChains == null || keyChains.isEmpty()) {
+            return;
+        }
+
+        List<String> args = new ArrayList<>();
+        args.add("security");
+        args.add("list-keychains");
+        args.add("-s");
+
+        args.addAll(keyChains);
+
+        ProcessBuilder  pb = new ProcessBuilder(args);
+        IOUtils.exec(pb);
+    }
+
+    public static void signAppBundle(
+            Map<String, ? super Object> params, Path appLocation,
+            String signingIdentity, String identifierPrefix,
+            String entitlementsFile, String inheritedEntitlements)
+            throws IOException {
+        AtomicReference<IOException> toThrow = new AtomicReference<>();
+        String appExecutable = "/Contents/MacOS/" + APP_NAME.fetchFrom(params);
+        String keyChain = SIGNING_KEYCHAIN.fetchFrom(params);
+
+        // sign all dylibs and jars
+        try (Stream<Path> stream = Files.walk(appLocation)) {
+            stream.peek(path -> { // fix permissions
+                try {
+                    Set<PosixFilePermission> pfp =
+                            Files.getPosixFilePermissions(path);
+                    if (!pfp.contains(PosixFilePermission.OWNER_WRITE)) {
+                        pfp = EnumSet.copyOf(pfp);
+                        pfp.add(PosixFilePermission.OWNER_WRITE);
+                        Files.setPosixFilePermissions(path, pfp);
+                    }
+                } catch (IOException e) {
+                    Log.verbose(e);
+                }
+            }).filter(p -> Files.isRegularFile(p)
+                      && !(p.toString().contains("/Contents/MacOS/libjli.dylib")
+                      || p.toString().endsWith(appExecutable)
+                      || p.toString().contains("/Contents/runtime")
+                      || p.toString().contains("/Contents/Frameworks"))).forEach(p -> {
+                //noinspection ThrowableResultOfMethodCallIgnored
+                if (toThrow.get() != null) return;
+
+                // If p is a symlink then skip the signing process.
+                if (Files.isSymbolicLink(p)) {
+                    if (VERBOSE.fetchFrom(params)) {
+                        Log.verbose(MessageFormat.format(I18N.getString(
+                                "message.ignoring.symlink"), p.toString()));
+                    }
+                } else {
+                    if (p.toString().endsWith(LIBRARY_NAME)) {
+                        if (isFileSigned(p)) {
+                            return;
+                        }
+                    }
+
+                    List<String> args = new ArrayList<>();
+                    args.addAll(Arrays.asList("codesign",
+                            "-s", signingIdentity, // sign with this key
+                            "--prefix", identifierPrefix,
+                            // use the identifier as a prefix
+                            "-vvvv"));
+                    if (entitlementsFile != null &&
+                            (p.toString().endsWith(".jar")
+                            || p.toString().endsWith(".dylib"))) {
+                        args.add("--entitlements");
+                        args.add(entitlementsFile); // entitlements
+                    } else if (inheritedEntitlements != null &&
+                            Files.isExecutable(p)) {
+                        args.add("--entitlements");
+                        args.add(inheritedEntitlements);
+                        // inherited entitlements for executable processes
+                    }
+                    if (keyChain != null && !keyChain.isEmpty()) {
+                        args.add("--keychain");
+                        args.add(keyChain);
+                    }
+                    args.add(p.toString());
+
+                    try {
+                        Set<PosixFilePermission> oldPermissions =
+                                Files.getPosixFilePermissions(p);
+                        File f = p.toFile();
+                        f.setWritable(true, true);
+
+                        ProcessBuilder pb = new ProcessBuilder(args);
+                        IOUtils.exec(pb);
+
+                        Files.setPosixFilePermissions(p, oldPermissions);
+                    } catch (IOException ioe) {
+                        toThrow.set(ioe);
+                    }
+                }
+            });
+        }
+        IOException ioe = toThrow.get();
+        if (ioe != null) {
+            throw ioe;
+        }
+
+        // sign all runtime and frameworks
+        Consumer<? super Path> signIdentifiedByPList = path -> {
+            //noinspection ThrowableResultOfMethodCallIgnored
+            if (toThrow.get() != null) return;
+
+            try {
+                List<String> args = new ArrayList<>();
+                args.addAll(Arrays.asList("codesign",
+                        "-s", signingIdentity, // sign with this key
+                        "--prefix", identifierPrefix,
+                        // use the identifier as a prefix
+                        "-vvvv"));
+                if (keyChain != null && !keyChain.isEmpty()) {
+                    args.add("--keychain");
+                    args.add(keyChain);
+                }
+                args.add(path.toString());
+                ProcessBuilder pb = new ProcessBuilder(args);
+                IOUtils.exec(pb);
+
+                args = new ArrayList<>();
+                args.addAll(Arrays.asList("codesign",
+                        "-s", signingIdentity, // sign with this key
+                        "--prefix", identifierPrefix,
+                        // use the identifier as a prefix
+                        "-vvvv"));
+                if (keyChain != null && !keyChain.isEmpty()) {
+                    args.add("--keychain");
+                    args.add(keyChain);
+                }
+                args.add(path.toString()
+                        + "/Contents/_CodeSignature/CodeResources");
+                pb = new ProcessBuilder(args);
+                IOUtils.exec(pb);
+            } catch (IOException e) {
+                toThrow.set(e);
+            }
+        };
+
+        Path javaPath = appLocation.resolve("Contents/runtime");
+        if (Files.isDirectory(javaPath)) {
+            signIdentifiedByPList.accept(javaPath);
+
+            ioe = toThrow.get();
+            if (ioe != null) {
+                throw ioe;
+            }
+        }
+        Path frameworkPath = appLocation.resolve("Contents/Frameworks");
+        if (Files.isDirectory(frameworkPath)) {
+            Files.list(frameworkPath)
+                    .forEach(signIdentifiedByPList);
+
+            ioe = toThrow.get();
+            if (ioe != null) {
+                throw ioe;
+            }
+        }
+
+        // sign the app itself
+        List<String> args = new ArrayList<>();
+        args.addAll(Arrays.asList("codesign",
+                "-s", signingIdentity, // sign with this key
+                "-vvvv")); // super verbose output
+        if (entitlementsFile != null) {
+            args.add("--entitlements");
+            args.add(entitlementsFile); // entitlements
+        }
+        if (keyChain != null && !keyChain.isEmpty()) {
+            args.add("--keychain");
+            args.add(keyChain);
+        }
+        args.add(appLocation.toString());
+
+        ProcessBuilder pb =
+                new ProcessBuilder(args.toArray(new String[args.size()]));
+        IOUtils.exec(pb);
+    }
+
+    private static boolean isFileSigned(Path file) {
+        ProcessBuilder pb =
+                new ProcessBuilder("codesign", "--verify", file.toString());
+
+        try {
+            IOUtils.exec(pb);
+        } catch (IOException ex) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private static String extractBundleIdentifier(Map<String, Object> params) {
+        if (PREDEFINED_APP_IMAGE.fetchFrom(params) == null) {
+            return null;
+        }
+
+        try {
+            File infoPList = new File(PREDEFINED_APP_IMAGE.fetchFrom(params) +
+                                      File.separator + "Contents" +
+                                      File.separator + "Info.plist");
+
+            DocumentBuilderFactory dbf
+                    = DocumentBuilderFactory.newDefaultInstance();
+            dbf.setFeature("http://apache.org/xml/features/" +
+                           "nonvalidating/load-external-dtd", false);
+            DocumentBuilder b = dbf.newDocumentBuilder();
+            org.w3c.dom.Document doc = b.parse(new FileInputStream(
+                    infoPList.getAbsolutePath()));
+
+            XPath xPath = XPathFactory.newInstance().newXPath();
+            // Query for the value of <string> element preceding <key>
+            // element with value equal to CFBundleIdentifier
+            String v = (String) xPath.evaluate(
+                    "//string[preceding-sibling::key = \"CFBundleIdentifier\"][1]",
+                    doc, XPathConstants.STRING);
+
+            if (v != null && !v.isEmpty()) {
+                return v;
+            }
+        } catch (Exception ex) {
+            Log.verbose(ex);
+        }
+
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppStoreBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.*;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+import static jdk.incubator.jpackage.internal.MacAppBundler.*;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+
+public class MacAppStoreBundler extends MacBaseInstallerBundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MacResources");
+
+    private static final String TEMPLATE_BUNDLE_ICON_HIDPI = "java.icns";
+    private final static String DEFAULT_ENTITLEMENTS =
+            "MacAppStore.entitlements";
+    private final static String DEFAULT_INHERIT_ENTITLEMENTS =
+            "MacAppStore_Inherit.entitlements";
+
+    public static final BundlerParamInfo<String> MAC_APP_STORE_APP_SIGNING_KEY =
+            new StandardBundlerParam<>(
+            "mac.signing-key-app",
+            String.class,
+            params -> {
+                String result = MacBaseInstallerBundler.findKey(
+                        "3rd Party Mac Developer Application: " +
+                        SIGNING_KEY_USER.fetchFrom(params),
+                        SIGNING_KEYCHAIN.fetchFrom(params),
+                        VERBOSE.fetchFrom(params));
+                if (result != null) {
+                    MacCertificate certificate = new MacCertificate(result);
+
+                    if (!certificate.isValid()) {
+                        Log.error(MessageFormat.format(
+                                I18N.getString("error.certificate.expired"),
+                                result));
+                    }
+                }
+
+                return result;
+            },
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<String> MAC_APP_STORE_PKG_SIGNING_KEY =
+            new StandardBundlerParam<>(
+            "mac.signing-key-pkg",
+            String.class,
+            params -> {
+                String result = MacBaseInstallerBundler.findKey(
+                        "3rd Party Mac Developer Installer: " +
+                        SIGNING_KEY_USER.fetchFrom(params),
+                        SIGNING_KEYCHAIN.fetchFrom(params),
+                        VERBOSE.fetchFrom(params));
+
+                if (result != null) {
+                    MacCertificate certificate = new MacCertificate(result);
+
+                    if (!certificate.isValid()) {
+                        Log.error(MessageFormat.format(
+                                I18N.getString("error.certificate.expired"),
+                                result));
+                    }
+                }
+
+                return result;
+            },
+            (s, p) -> s);
+
+    public static final StandardBundlerParam<File> MAC_APP_STORE_ENTITLEMENTS  =
+            new StandardBundlerParam<>(
+            Arguments.CLIOptions.MAC_APP_STORE_ENTITLEMENTS.getId(),
+            File.class,
+            params -> null,
+            (s, p) -> new File(s));
+
+    public static final BundlerParamInfo<String> INSTALLER_SUFFIX =
+            new StandardBundlerParam<> (
+            "mac.app-store.installerName.suffix",
+            String.class,
+            params -> "-MacAppStore",
+            (s, p) -> s);
+
+    public File bundle(Map<String, ? super Object> params,
+            File outdir) throws PackagerException {
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.building-bundle"), APP_NAME.fetchFrom(params)));
+
+        IOUtils.writableOutputDir(outdir.toPath());
+
+        // first, load in some overrides
+        // icns needs @2 versions, so load in the @2 default
+        params.put(DEFAULT_ICNS_ICON.getID(), TEMPLATE_BUNDLE_ICON_HIDPI);
+
+        // now we create the app
+        File appImageDir = APP_IMAGE_TEMP_ROOT.fetchFrom(params);
+        try {
+            appImageDir.mkdirs();
+
+            try {
+                MacAppImageBuilder.addNewKeychain(params);
+            } catch (InterruptedException e) {
+                Log.error(e.getMessage());
+            }
+            // first, make sure we don't use the local signing key
+            params.put(DEVELOPER_ID_APP_SIGNING_KEY.getID(), null);
+            File appLocation = prepareAppBundle(params);
+
+            prepareEntitlements(params);
+
+            String signingIdentity =
+                    MAC_APP_STORE_APP_SIGNING_KEY.fetchFrom(params);
+            String identifierPrefix =
+                    BUNDLE_ID_SIGNING_PREFIX.fetchFrom(params);
+            String entitlementsFile =
+                    getConfig_Entitlements(params).toString();
+            String inheritEntitlements =
+                    getConfig_Inherit_Entitlements(params).toString();
+
+            MacAppImageBuilder.signAppBundle(params, appLocation.toPath(),
+                    signingIdentity, identifierPrefix,
+                    entitlementsFile, inheritEntitlements);
+            MacAppImageBuilder.restoreKeychainList(params);
+
+            ProcessBuilder pb;
+
+            // create the final pkg file
+            File finalPKG = new File(outdir, INSTALLER_NAME.fetchFrom(params)
+                    + INSTALLER_SUFFIX.fetchFrom(params)
+                    + ".pkg");
+            outdir.mkdirs();
+
+            String installIdentify =
+                    MAC_APP_STORE_PKG_SIGNING_KEY.fetchFrom(params);
+
+            List<String> buildOptions = new ArrayList<>();
+            buildOptions.add("productbuild");
+            buildOptions.add("--component");
+            buildOptions.add(appLocation.toString());
+            buildOptions.add("/Applications");
+            buildOptions.add("--sign");
+            buildOptions.add(installIdentify);
+            buildOptions.add("--product");
+            buildOptions.add(appLocation + "/Contents/Info.plist");
+            String keychainName = SIGNING_KEYCHAIN.fetchFrom(params);
+            if (keychainName != null && !keychainName.isEmpty()) {
+                buildOptions.add("--keychain");
+                buildOptions.add(keychainName);
+            }
+            buildOptions.add(finalPKG.getAbsolutePath());
+
+            pb = new ProcessBuilder(buildOptions);
+
+            IOUtils.exec(pb);
+            return finalPKG;
+        } catch (PackagerException pe) {
+            throw pe;
+        } catch (Exception ex) {
+            Log.verbose(ex);
+            throw new PackagerException(ex);
+        }
+    }
+
+    private File getConfig_Entitlements(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + ".entitlements");
+    }
+
+    private File getConfig_Inherit_Entitlements(
+            Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + "_Inherit.entitlements");
+    }
+
+    private void prepareEntitlements(Map<String, ? super Object> params)
+            throws IOException {
+        createResource(DEFAULT_ENTITLEMENTS, params)
+                .setCategory(
+                        I18N.getString("resource.mac-app-store-entitlements"))
+                .setExternal(MAC_APP_STORE_ENTITLEMENTS.fetchFrom(params))
+                .saveToFile(getConfig_Entitlements(params));
+
+        createResource(DEFAULT_INHERIT_ENTITLEMENTS, params)
+                .setCategory(I18N.getString(
+                        "resource.mac-app-store-inherit-entitlements"))
+                .saveToFile(getConfig_Entitlements(params));
+    }
+
+    ///////////////////////////////////////////////////////////////////////
+    // Implement Bundler
+    ///////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String getName() {
+        return I18N.getString("store.bundler.name");
+    }
+
+    @Override
+    public String getID() {
+        return "mac.appStore";
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws ConfigException {
+        try {
+            Objects.requireNonNull(params);
+
+            // hdiutil is always available so there's no need to test for
+            // availability.
+            // run basic validation to ensure requirements are met
+
+            // we are not interested in return code, only possible exception
+            validateAppImageAndBundeler(params);
+
+            // reject explicitly set to not sign
+            if (!Optional.ofNullable(MacAppImageBuilder.
+                    SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) {
+                throw new ConfigException(
+                        I18N.getString("error.must-sign-app-store"),
+                        I18N.getString("error.must-sign-app-store.advice"));
+            }
+
+            // make sure we have settings for signatures
+            if (MAC_APP_STORE_APP_SIGNING_KEY.fetchFrom(params) == null) {
+                throw new ConfigException(
+                        I18N.getString("error.no-app-signing-key"),
+                        I18N.getString("error.no-app-signing-key.advice"));
+            }
+            if (MAC_APP_STORE_PKG_SIGNING_KEY.fetchFrom(params) == null) {
+                throw new ConfigException(
+                        I18N.getString("error.no-pkg-signing-key"),
+                        I18N.getString("error.no-pkg-signing-key.advice"));
+            }
+
+            // things we could check...
+            // check the icons, make sure it has hidpi icons
+            // check the category,
+            // make sure it fits in the list apple has provided
+            // validate bundle identifier is reverse dns
+            // check for \a+\.\a+\..
+
+            return true;
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) throws PackagerException {
+        return bundle(params, outputParentDir);
+    }
+
+    @Override
+    public boolean supported(boolean runtimeInstaller) {
+        // return (!runtimeInstaller &&
+        //         Platform.getPlatform() == Platform.MAC);
+        return false; // mac-app-store not yet supported
+    }
+
+    @Override
+    public boolean isDefault() {
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacBaseInstallerBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+public abstract class MacBaseInstallerBundler extends AbstractBundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MacResources");
+
+    // This could be generalized more to be for any type of Image Bundler
+    public static final BundlerParamInfo<MacAppBundler> APP_BUNDLER =
+            new StandardBundlerParam<>(
+            "mac.app.bundler",
+            MacAppBundler.class,
+            params -> new MacAppBundler(),
+            (s, p) -> null);
+
+    public final BundlerParamInfo<File> APP_IMAGE_TEMP_ROOT =
+            new StandardBundlerParam<>(
+            "mac.app.imageRoot",
+            File.class,
+            params -> {
+                File imageDir = IMAGES_ROOT.fetchFrom(params);
+                if (!imageDir.exists()) imageDir.mkdirs();
+                try {
+                    return Files.createTempDirectory(
+                            imageDir.toPath(), "image-").toFile();
+                } catch (IOException e) {
+                    return new File(imageDir, getID()+ ".image");
+                }
+            },
+            (s, p) -> new File(s));
+
+    public static final BundlerParamInfo<String> SIGNING_KEY_USER =
+            new StandardBundlerParam<>(
+            Arguments.CLIOptions.MAC_SIGNING_KEY_NAME.getId(),
+            String.class,
+            params -> "",
+            null);
+
+    public static final BundlerParamInfo<String> SIGNING_KEYCHAIN =
+            new StandardBundlerParam<>(
+            Arguments.CLIOptions.MAC_SIGNING_KEYCHAIN.getId(),
+            String.class,
+            params -> "",
+            null);
+
+    public static final BundlerParamInfo<String> INSTALLER_NAME =
+            new StandardBundlerParam<> (
+            "mac.installerName",
+            String.class,
+            params -> {
+                String nm = APP_NAME.fetchFrom(params);
+                if (nm == null) return null;
+
+                String version = VERSION.fetchFrom(params);
+                if (version == null) {
+                    return nm;
+                } else {
+                    return nm + "-" + version;
+                }
+            },
+            (s, p) -> s);
+
+    protected void validateAppImageAndBundeler(
+            Map<String, ? super Object> params) throws ConfigException {
+        if (PREDEFINED_APP_IMAGE.fetchFrom(params) != null) {
+            File applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params);
+            if (!applicationImage.exists()) {
+                throw new ConfigException(
+                        MessageFormat.format(I18N.getString(
+                                "message.app-image-dir-does-not-exist"),
+                                PREDEFINED_APP_IMAGE.getID(),
+                                applicationImage.toString()),
+                        MessageFormat.format(I18N.getString(
+                                "message.app-image-dir-does-not-exist.advice"),
+                                PREDEFINED_APP_IMAGE.getID()));
+            }
+            if (APP_NAME.fetchFrom(params) == null) {
+                throw new ConfigException(
+                        I18N.getString("message.app-image-requires-app-name"),
+                        I18N.getString(
+                            "message.app-image-requires-app-name.advice"));
+            }
+        } else {
+            APP_BUNDLER.fetchFrom(params).validate(params);
+        }
+    }
+
+    protected File prepareAppBundle(Map<String, ? super Object> params)
+            throws PackagerException {
+        File predefinedImage =
+                StandardBundlerParam.getPredefinedAppImage(params);
+        if (predefinedImage != null) {
+            return predefinedImage;
+        }
+        File appImageRoot = APP_IMAGE_TEMP_ROOT.fetchFrom(params);
+
+        return APP_BUNDLER.fetchFrom(params).doBundle(
+                params, appImageRoot, true);
+    }
+
+    @Override
+    public String getBundleType() {
+        return "INSTALLER";
+    }
+
+    public static String findKey(String key, String keychainName,
+            boolean verbose) {
+        if (Platform.getPlatform() != Platform.MAC) {
+            return null;
+        }
+
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                PrintStream ps = new PrintStream(baos)) {
+            List<String> searchOptions = new ArrayList<>();
+            searchOptions.add("security");
+            searchOptions.add("find-certificate");
+            searchOptions.add("-c");
+            searchOptions.add(key);
+            searchOptions.add("-a");
+            if (keychainName != null && !keychainName.isEmpty()) {
+                searchOptions.add(keychainName);
+            }
+
+            ProcessBuilder pb = new ProcessBuilder(searchOptions);
+
+            IOUtils.exec(pb, false, ps);
+            Pattern p = Pattern.compile("\"alis\"<blob>=\"([^\"]+)\"");
+            Matcher m = p.matcher(baos.toString());
+            if (!m.find()) {
+                Log.error("Did not find a key matching '" + key + "'");
+                return null;
+            }
+            String matchedKey = m.group(1);
+            if (m.find()) {
+                Log.error("Found more than one key matching '"  + key + "'");
+                return null;
+            }
+            Log.verbose("Using key '" + matchedKey + "'");
+            return matchedKey;
+        } catch (IOException ioe) {
+            Log.verbose(ioe);
+            return null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacCertificate.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2016, 2019, 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.incubator.jpackage.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.Files;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+public final class MacCertificate {
+    private final String certificate;
+
+    public MacCertificate(String certificate) {
+        this.certificate = certificate;
+    }
+
+    public boolean isValid() {
+        return verifyCertificate(this.certificate);
+    }
+
+    private static File findCertificate(String certificate) {
+        File result = null;
+
+        List<String> args = new ArrayList<>();
+        args.add("security");
+        args.add("find-certificate");
+        args.add("-c");
+        args.add(certificate);
+        args.add("-a");
+        args.add("-p");
+
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                PrintStream ps = new PrintStream(baos)) {
+            ProcessBuilder security = new ProcessBuilder(args);
+            IOUtils.exec(security, false, ps);
+
+            File output = File.createTempFile("tempfile", ".tmp");
+
+            Files.copy(new ByteArrayInputStream(baos.toByteArray()),
+                    output.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+            result = output;
+        }
+        catch (IOException ignored) {}
+
+        return result;
+    }
+
+    private static Date findCertificateDate(String filename) {
+        Date result = null;
+
+        List<String> args = new ArrayList<>();
+        args.add("/usr/bin/openssl");
+        args.add("x509");
+        args.add("-noout");
+        args.add("-enddate");
+        args.add("-in");
+        args.add(filename);
+
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                PrintStream ps = new PrintStream(baos)) {
+            ProcessBuilder security = new ProcessBuilder(args);
+            IOUtils.exec(security, false, ps);
+            String output = baos.toString();
+            output = output.substring(output.indexOf("=") + 1);
+            DateFormat df = new SimpleDateFormat(
+                    "MMM dd kk:mm:ss yyyy z", Locale.ENGLISH);
+            result = df.parse(output);
+        } catch (IOException | ParseException ex) {
+            Log.verbose(ex);
+        }
+
+        return result;
+    }
+
+    private static boolean verifyCertificate(String certificate) {
+        boolean result = false;
+
+        try {
+            File file = null;
+            Date certificateDate = null;
+
+            try {
+                file = findCertificate(certificate);
+
+                if (file != null) {
+                    certificateDate = findCertificateDate(
+                            file.getCanonicalPath());
+                }
+            }
+            finally {
+                if (file != null) {
+                    file.delete();
+                }
+            }
+
+            if (certificateDate != null) {
+                Calendar c = Calendar.getInstance();
+                Date today = c.getTime();
+
+                if (certificateDate.after(today)) {
+                    result = true;
+                }
+            }
+        }
+        catch (IOException ignored) {}
+
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacDmgBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.text.MessageFormat;
+import java.util.*;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+public class MacDmgBundler extends MacBaseInstallerBundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MacResources");
+
+    static final String DEFAULT_BACKGROUND_IMAGE="background_dmg.png";
+    static final String DEFAULT_DMG_SETUP_SCRIPT="DMGsetup.scpt";
+    static final String TEMPLATE_BUNDLE_ICON = "java.icns";
+
+    static final String DEFAULT_LICENSE_PLIST="lic_template.plist";
+
+    public static final BundlerParamInfo<String> INSTALLER_SUFFIX =
+            new StandardBundlerParam<> (
+            "mac.dmg.installerName.suffix",
+            String.class,
+            params -> "",
+            (s, p) -> s);
+
+    public File bundle(Map<String, ? super Object> params,
+            File outdir) throws PackagerException {
+        Log.verbose(MessageFormat.format(I18N.getString("message.building-dmg"),
+                APP_NAME.fetchFrom(params)));
+
+        IOUtils.writableOutputDir(outdir.toPath());
+
+        File appImageDir = APP_IMAGE_TEMP_ROOT.fetchFrom(params);
+        try {
+            appImageDir.mkdirs();
+
+            if (prepareAppBundle(params) != null &&
+                    prepareConfigFiles(params)) {
+                File configScript = getConfig_Script(params);
+                if (configScript.exists()) {
+                    Log.verbose(MessageFormat.format(
+                            I18N.getString("message.running-script"),
+                            configScript.getAbsolutePath()));
+                    IOUtils.run("bash", configScript);
+                }
+
+                return buildDMG(params, outdir);
+            }
+            return null;
+        } catch (IOException ex) {
+            Log.verbose(ex);
+            throw new PackagerException(ex);
+        }
+    }
+
+    private static final String hdiutil = "/usr/bin/hdiutil";
+
+    private void prepareDMGSetupScript(String volumeName,
+            Map<String, ? super Object> params) throws IOException {
+        File dmgSetup = getConfig_VolumeScript(params);
+        Log.verbose(MessageFormat.format(
+                I18N.getString("message.preparing-dmg-setup"),
+                dmgSetup.getAbsolutePath()));
+
+        //prepare config for exe
+        Map<String, String> data = new HashMap<>();
+        data.put("DEPLOY_ACTUAL_VOLUME_NAME", volumeName);
+        data.put("DEPLOY_APPLICATION_NAME", APP_NAME.fetchFrom(params));
+
+        data.put("DEPLOY_INSTALL_LOCATION", "(path to applications folder)");
+        data.put("DEPLOY_INSTALL_NAME", "Applications");
+
+        createResource(DEFAULT_DMG_SETUP_SCRIPT, params)
+                .setCategory(I18N.getString("resource.dmg-setup-script"))
+                .setSubstitutionData(data)
+                .saveToFile(dmgSetup);
+    }
+
+    private File getConfig_VolumeScript(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + "-dmg-setup.scpt");
+    }
+
+    private File getConfig_VolumeBackground(
+            Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + "-background.png");
+    }
+
+    private File getConfig_VolumeIcon(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + "-volume.icns");
+    }
+
+    private File getConfig_LicenseFile(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + "-license.plist");
+    }
+
+    private void prepareLicense(Map<String, ? super Object> params) {
+        try {
+            String licFileStr = LICENSE_FILE.fetchFrom(params);
+            if (licFileStr == null) {
+                return;
+            }
+
+            File licFile = new File(licFileStr);
+            byte[] licenseContentOriginal =
+                    Files.readAllBytes(licFile.toPath());
+            String licenseInBase64 =
+                    Base64.getEncoder().encodeToString(licenseContentOriginal);
+
+            Map<String, String> data = new HashMap<>();
+            data.put("APPLICATION_LICENSE_TEXT", licenseInBase64);
+
+            createResource(DEFAULT_LICENSE_PLIST, params)
+                    .setCategory(I18N.getString("resource.license-setup"))
+                    .setSubstitutionData(data)
+                    .saveToFile(getConfig_LicenseFile(params));
+
+        } catch (IOException ex) {
+            Log.verbose(ex);
+        }
+    }
+
+    private boolean prepareConfigFiles(Map<String, ? super Object> params)
+            throws IOException {
+
+        createResource(DEFAULT_BACKGROUND_IMAGE, params)
+                    .setCategory(I18N.getString("resource.dmg-background"))
+                    .saveToFile(getConfig_VolumeBackground(params));
+
+        createResource(TEMPLATE_BUNDLE_ICON, params)
+                .setCategory(I18N.getString("resource.volume-icon"))
+                .setExternal(MacAppBundler.ICON_ICNS.fetchFrom(params))
+                .saveToFile(getConfig_VolumeIcon(params));
+
+        createResource(null, params)
+                .setCategory(I18N.getString("resource.post-install-script"))
+                .saveToFile(getConfig_Script(params));
+
+        prepareLicense(params);
+
+        // In theory we need to extract name from results of attach command
+        // However, this will be a problem for customization as name will
+        // possibly change every time and developer will not be able to fix it
+        // As we are using tmp dir chance we get "different" name are low =>
+        // Use fixed name we used for bundle
+        prepareDMGSetupScript(APP_NAME.fetchFrom(params), params);
+
+        return true;
+    }
+
+    // name of post-image script
+    private File getConfig_Script(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + "-post-image.sh");
+    }
+
+    // Location of SetFile utility may be different depending on MacOS version
+    // We look for several known places and if none of them work will
+    // try ot find it
+    private String findSetFileUtility() {
+        String typicalPaths[] = {"/Developer/Tools/SetFile",
+                "/usr/bin/SetFile", "/Developer/usr/bin/SetFile"};
+
+        String setFilePath = null;
+        for (String path: typicalPaths) {
+            File f = new File(path);
+            if (f.exists() && f.canExecute()) {
+                setFilePath = path;
+                break;
+            }
+        }
+
+        // Validate SetFile, if Xcode is not installed it will run, but exit with error
+        // code
+        if (setFilePath != null) {
+            try {
+                ProcessBuilder pb = new ProcessBuilder(setFilePath, "-h");
+                Process p = pb.start();
+                int code = p.waitFor();
+                if (code == 0) {
+                    return setFilePath;
+                }
+            } catch (Exception ignored) {}
+
+            // No need for generic find attempt. We found it, but it does not work.
+            // Probably due to missing xcode.
+            return null;
+        }
+
+        // generic find attempt
+        try {
+            ProcessBuilder pb = new ProcessBuilder("xcrun", "-find", "SetFile");
+            Process p = pb.start();
+            InputStreamReader isr = new InputStreamReader(p.getInputStream());
+            BufferedReader br = new BufferedReader(isr);
+            String lineRead = br.readLine();
+            if (lineRead != null) {
+                File f = new File(lineRead);
+                if (f.exists() && f.canExecute()) {
+                    return f.getAbsolutePath();
+                }
+            }
+        } catch (IOException ignored) {}
+
+        return null;
+    }
+
+    private File buildDMG(
+            Map<String, ? super Object> params, File outdir)
+            throws IOException {
+        File imagesRoot = IMAGES_ROOT.fetchFrom(params);
+        if (!imagesRoot.exists()) imagesRoot.mkdirs();
+
+        File protoDMG = new File(imagesRoot,
+                APP_NAME.fetchFrom(params) +"-tmp.dmg");
+        File finalDMG = new File(outdir, INSTALLER_NAME.fetchFrom(params)
+                + INSTALLER_SUFFIX.fetchFrom(params) + ".dmg");
+
+        File srcFolder = APP_IMAGE_TEMP_ROOT.fetchFrom(params);
+        File predefinedImage =
+                StandardBundlerParam.getPredefinedAppImage(params);
+        if (predefinedImage != null) {
+            srcFolder = predefinedImage;
+        }
+
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.creating-dmg-file"), finalDMG.getAbsolutePath()));
+
+        protoDMG.delete();
+        if (finalDMG.exists() && !finalDMG.delete()) {
+            throw new IOException(MessageFormat.format(I18N.getString(
+                    "message.dmg-cannot-be-overwritten"),
+                    finalDMG.getAbsolutePath()));
+        }
+
+        protoDMG.getParentFile().mkdirs();
+        finalDMG.getParentFile().mkdirs();
+
+        String hdiUtilVerbosityFlag = VERBOSE.fetchFrom(params) ?
+                "-verbose" : "-quiet";
+
+        // create temp image
+        ProcessBuilder pb = new ProcessBuilder(
+                hdiutil,
+                "create",
+                hdiUtilVerbosityFlag,
+                "-srcfolder", srcFolder.getAbsolutePath(),
+                "-volname", APP_NAME.fetchFrom(params),
+                "-ov", protoDMG.getAbsolutePath(),
+                "-fs", "HFS+",
+                "-format", "UDRW");
+        IOUtils.exec(pb);
+
+        // mount temp image
+        pb = new ProcessBuilder(
+                hdiutil,
+                "attach",
+                protoDMG.getAbsolutePath(),
+                hdiUtilVerbosityFlag,
+                "-mountroot", imagesRoot.getAbsolutePath());
+        IOUtils.exec(pb);
+
+        File mountedRoot = new File(imagesRoot.getAbsolutePath(),
+                    APP_NAME.fetchFrom(params));
+
+        try {
+            // volume icon
+            File volumeIconFile = new File(mountedRoot, ".VolumeIcon.icns");
+            IOUtils.copyFile(getConfig_VolumeIcon(params),
+                    volumeIconFile);
+
+            // background image
+            File bgdir = new File(mountedRoot, ".background");
+            bgdir.mkdirs();
+            IOUtils.copyFile(getConfig_VolumeBackground(params),
+                    new File(bgdir, "background.png"));
+
+            // Indicate that we want a custom icon
+            // NB: attributes of the root directory are ignored
+            // when creating the volume
+            // Therefore we have to do this after we mount image
+            String setFileUtility = findSetFileUtility();
+            if (setFileUtility != null) {
+                //can not find utility => keep going without icon
+                try {
+                    volumeIconFile.setWritable(true);
+                    // The "creator" attribute on a file is a legacy attribute
+                    // but it seems Finder excepts these bytes to be
+                    // "icnC" for the volume icon
+                    // (might not work on Mac 10.13 with old XCode)
+                    pb = new ProcessBuilder(
+                            setFileUtility,
+                            "-c", "icnC",
+                            volumeIconFile.getAbsolutePath());
+                    IOUtils.exec(pb);
+                    volumeIconFile.setReadOnly();
+
+                    pb = new ProcessBuilder(
+                            setFileUtility,
+                            "-a", "C",
+                            mountedRoot.getAbsolutePath());
+                    IOUtils.exec(pb);
+                } catch (IOException ex) {
+                    Log.error(ex.getMessage());
+                    Log.verbose("Cannot enable custom icon using SetFile utility");
+                }
+            } else {
+                Log.verbose(I18N.getString("message.setfile.dmg"));
+            }
+
+            // We will not consider setting background image and creating link to
+            // /Application folder in DMG as critical error, since it can fail in
+            // headless enviroment.
+            try {
+                pb = new ProcessBuilder("osascript",
+                        getConfig_VolumeScript(params).getAbsolutePath());
+                IOUtils.exec(pb);
+            } catch (IOException ex) {
+                Log.verbose(ex);
+            }
+        } finally {
+            // Detach the temporary image
+            pb = new ProcessBuilder(
+                    hdiutil,
+                    "detach",
+                    "-force",
+                    hdiUtilVerbosityFlag,
+                    mountedRoot.getAbsolutePath());
+            IOUtils.exec(pb);
+        }
+
+        // Compress it to a new image
+        pb = new ProcessBuilder(
+                hdiutil,
+                "convert",
+                protoDMG.getAbsolutePath(),
+                hdiUtilVerbosityFlag,
+                "-format", "UDZO",
+                "-o", finalDMG.getAbsolutePath());
+        IOUtils.exec(pb);
+
+        //add license if needed
+        if (getConfig_LicenseFile(params).exists()) {
+            //hdiutil unflatten your_image_file.dmg
+            pb = new ProcessBuilder(
+                    hdiutil,
+                    "unflatten",
+                    finalDMG.getAbsolutePath()
+            );
+            IOUtils.exec(pb);
+
+            //add license
+            pb = new ProcessBuilder(
+                    hdiutil,
+                    "udifrez",
+                    finalDMG.getAbsolutePath(),
+                    "-xml",
+                    getConfig_LicenseFile(params).getAbsolutePath()
+            );
+            IOUtils.exec(pb);
+
+            //hdiutil flatten your_image_file.dmg
+            pb = new ProcessBuilder(
+                    hdiutil,
+                    "flatten",
+                    finalDMG.getAbsolutePath()
+            );
+            IOUtils.exec(pb);
+
+        }
+
+        //Delete the temporary image
+        protoDMG.delete();
+
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.output-to-location"),
+                APP_NAME.fetchFrom(params), finalDMG.getAbsolutePath()));
+
+        return finalDMG;
+    }
+
+
+    //////////////////////////////////////////////////////////////////////////
+    // Implement Bundler
+    //////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String getName() {
+        return I18N.getString("dmg.bundler.name");
+    }
+
+    @Override
+    public String getID() {
+        return "dmg";
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws ConfigException {
+        try {
+            Objects.requireNonNull(params);
+
+            //run basic validation to ensure requirements are met
+            //we are not interested in return code, only possible exception
+            validateAppImageAndBundeler(params);
+
+            return true;
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) throws PackagerException {
+        return bundle(params, outputParentDir);
+    }
+
+    @Override
+    public boolean supported(boolean runtimeInstaller) {
+        return isSupported();
+    }
+
+    public final static String[] required =
+            {"/usr/bin/hdiutil", "/usr/bin/osascript"};
+    public static boolean isSupported() {
+        try {
+            for (String s : required) {
+                File f = new File(s);
+                if (!f.exists() || !f.canExecute()) {
+                    return false;
+                }
+            }
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean isDefault() {
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacPkgBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,555 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.io.*;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+import java.util.*;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+import static jdk.incubator.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
+import static jdk.incubator.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEY_USER;
+import static jdk.incubator.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+
+public class MacPkgBundler extends MacBaseInstallerBundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MacResources");
+
+    private static final String DEFAULT_BACKGROUND_IMAGE = "background_pkg.png";
+
+    private static final String TEMPLATE_PREINSTALL_SCRIPT =
+            "preinstall.template";
+    private static final String TEMPLATE_POSTINSTALL_SCRIPT =
+            "postinstall.template";
+
+    private static final BundlerParamInfo<File> PACKAGES_ROOT =
+            new StandardBundlerParam<>(
+            "mac.pkg.packagesRoot",
+            File.class,
+            params -> {
+                File packagesRoot =
+                        new File(TEMP_ROOT.fetchFrom(params), "packages");
+                packagesRoot.mkdirs();
+                return packagesRoot;
+            },
+            (s, p) -> new File(s));
+
+
+    protected final BundlerParamInfo<File> SCRIPTS_DIR =
+            new StandardBundlerParam<>(
+            "mac.pkg.scriptsDir",
+            File.class,
+            params -> {
+                File scriptsDir =
+                        new File(CONFIG_ROOT.fetchFrom(params), "scripts");
+                scriptsDir.mkdirs();
+                return scriptsDir;
+            },
+            (s, p) -> new File(s));
+
+    public static final
+            BundlerParamInfo<String> DEVELOPER_ID_INSTALLER_SIGNING_KEY =
+            new StandardBundlerParam<>(
+            "mac.signing-key-developer-id-installer",
+            String.class,
+            params -> {
+                    String result = MacBaseInstallerBundler.findKey(
+                            "Developer ID Installer: "
+                            + SIGNING_KEY_USER.fetchFrom(params),
+                            SIGNING_KEYCHAIN.fetchFrom(params),
+                            VERBOSE.fetchFrom(params));
+                    if (result != null) {
+                        MacCertificate certificate = new MacCertificate(result);
+
+                        if (!certificate.isValid()) {
+                            Log.error(MessageFormat.format(
+                                    I18N.getString("error.certificate.expired"),
+                                    result));
+                        }
+                    }
+
+                    return result;
+                },
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<String> MAC_INSTALL_DIR =
+            new StandardBundlerParam<>(
+            "mac-install-dir",
+            String.class,
+             params -> {
+                 String dir = INSTALL_DIR.fetchFrom(params);
+                 return (dir != null) ? dir : "/Applications";
+             },
+            (s, p) -> s
+    );
+
+    public static final BundlerParamInfo<String> INSTALLER_SUFFIX =
+            new StandardBundlerParam<> (
+            "mac.pkg.installerName.suffix",
+            String.class,
+            params -> "",
+            (s, p) -> s);
+
+    public File bundle(Map<String, ? super Object> params,
+            File outdir) throws PackagerException {
+        Log.verbose(MessageFormat.format(I18N.getString("message.building-pkg"),
+                APP_NAME.fetchFrom(params)));
+
+        IOUtils.writableOutputDir(outdir.toPath());
+
+        try {
+            File appImageDir = prepareAppBundle(params);
+
+            if (appImageDir != null && prepareConfigFiles(params)) {
+
+                File configScript = getConfig_Script(params);
+                if (configScript.exists()) {
+                    Log.verbose(MessageFormat.format(I18N.getString(
+                            "message.running-script"),
+                            configScript.getAbsolutePath()));
+                    IOUtils.run("bash", configScript);
+                }
+
+                return createPKG(params, outdir, appImageDir);
+            }
+            return null;
+        } catch (IOException ex) {
+            Log.verbose(ex);
+            throw new PackagerException(ex);
+        }
+    }
+
+    private File getPackages_AppPackage(Map<String, ? super Object> params) {
+        return new File(PACKAGES_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + "-app.pkg");
+    }
+
+    private File getConfig_DistributionXMLFile(
+            Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params), "distribution.dist");
+    }
+
+    private File getConfig_BackgroundImage(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + "-background.png");
+    }
+
+    private File getConfig_BackgroundImageDarkAqua(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + "-background-darkAqua.png");
+    }
+
+    private File getScripts_PreinstallFile(Map<String, ? super Object> params) {
+        return new File(SCRIPTS_DIR.fetchFrom(params), "preinstall");
+    }
+
+    private File getScripts_PostinstallFile(
+            Map<String, ? super Object> params) {
+        return new File(SCRIPTS_DIR.fetchFrom(params), "postinstall");
+    }
+
+    private String getAppIdentifier(Map<String, ? super Object> params) {
+        return MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params);
+    }
+
+    private void preparePackageScripts(Map<String, ? super Object> params)
+            throws IOException {
+        Log.verbose(I18N.getString("message.preparing-scripts"));
+
+        Map<String, String> data = new HashMap<>();
+
+        Path appLocation = Path.of(MAC_INSTALL_DIR.fetchFrom(params),
+                         APP_NAME.fetchFrom(params) + ".app", "Contents", "app");
+
+        data.put("INSTALL_LOCATION", MAC_INSTALL_DIR.fetchFrom(params));
+        data.put("APP_LOCATION", appLocation.toString());
+
+        createResource(TEMPLATE_PREINSTALL_SCRIPT, params)
+                .setCategory(I18N.getString("resource.pkg-preinstall-script"))
+                .setSubstitutionData(data)
+                .saveToFile(getScripts_PreinstallFile(params));
+        getScripts_PreinstallFile(params).setExecutable(true, false);
+
+        createResource(TEMPLATE_POSTINSTALL_SCRIPT, params)
+                .setCategory(I18N.getString("resource.pkg-postinstall-script"))
+                .setSubstitutionData(data)
+                .saveToFile(getScripts_PostinstallFile(params));
+        getScripts_PostinstallFile(params).setExecutable(true, false);
+    }
+
+    private static String URLEncoding(String pkgName) throws URISyntaxException {
+        URI uri = new URI(null, null, pkgName, null);
+        return uri.toASCIIString();
+    }
+
+    private void prepareDistributionXMLFile(Map<String, ? super Object> params)
+            throws IOException {
+        File f = getConfig_DistributionXMLFile(params);
+
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.preparing-distribution-dist"), f.getAbsolutePath()));
+
+        IOUtils.createXml(f.toPath(), xml -> {
+            xml.writeStartElement("installer-gui-script");
+            xml.writeAttribute("minSpecVersion", "1");
+
+            xml.writeStartElement("title");
+            xml.writeCharacters(APP_NAME.fetchFrom(params));
+            xml.writeEndElement();
+
+            xml.writeStartElement("background");
+            xml.writeAttribute("file", getConfig_BackgroundImage(params).getName());
+            xml.writeAttribute("mime-type", "image/png");
+            xml.writeAttribute("alignment", "bottomleft");
+            xml.writeAttribute("scaling", "none");
+            xml.writeEndElement();
+
+            xml.writeStartElement("background-darkAqua");
+            xml.writeAttribute("file", getConfig_BackgroundImageDarkAqua(params).getName());
+            xml.writeAttribute("mime-type", "image/png");
+            xml.writeAttribute("alignment", "bottomleft");
+            xml.writeAttribute("scaling", "none");
+            xml.writeEndElement();
+
+            String licFileStr = LICENSE_FILE.fetchFrom(params);
+            if (licFileStr != null) {
+                File licFile = new File(licFileStr);
+                xml.writeStartElement("license");
+                xml.writeAttribute("file", licFile.getAbsolutePath());
+                xml.writeAttribute("mime-type", "text/rtf");
+                xml.writeEndElement();
+            }
+
+            /*
+             * Note that the content of the distribution file
+             * below is generated by productbuild --synthesize
+             */
+            String appId = getAppIdentifier(params);
+
+            xml.writeStartElement("pkg-ref");
+            xml.writeAttribute("id", appId);
+            xml.writeEndElement(); // </pkg-ref>
+            xml.writeStartElement("options");
+            xml.writeAttribute("customize", "never");
+            xml.writeAttribute("require-scripts", "false");
+            xml.writeEndElement(); // </options>
+            xml.writeStartElement("choices-outline");
+            xml.writeStartElement("line");
+            xml.writeAttribute("choice", "default");
+            xml.writeStartElement("line");
+            xml.writeAttribute("choice", appId);
+            xml.writeEndElement(); // </line>
+            xml.writeEndElement(); // </line>
+            xml.writeEndElement(); // </choices-outline>
+            xml.writeStartElement("choice");
+            xml.writeAttribute("id", "default");
+            xml.writeEndElement(); // </choice>
+            xml.writeStartElement("choice");
+            xml.writeAttribute("id", appId);
+            xml.writeAttribute("visible", "false");
+            xml.writeStartElement("pkg-ref");
+            xml.writeAttribute("id", appId);
+            xml.writeEndElement(); // </pkg-ref>
+            xml.writeEndElement(); // </choice>
+            xml.writeStartElement("pkg-ref");
+            xml.writeAttribute("id", appId);
+            xml.writeAttribute("version", VERSION.fetchFrom(params));
+            xml.writeAttribute("onConclusion", "none");
+            try {
+                xml.writeCharacters(URLEncoding(
+                        getPackages_AppPackage(params).getName()));
+            } catch (URISyntaxException ex) {
+                throw new IOException(ex);
+            }
+            xml.writeEndElement(); // </pkg-ref>
+
+            xml.writeEndElement(); // </installer-gui-script>
+        });
+    }
+
+    private boolean prepareConfigFiles(Map<String, ? super Object> params)
+            throws IOException {
+
+        createResource(DEFAULT_BACKGROUND_IMAGE, params)
+                .setCategory(I18N.getString("resource.pkg-background-image"))
+                .saveToFile(getConfig_BackgroundImage(params));
+
+        createResource(DEFAULT_BACKGROUND_IMAGE, params)
+                .setCategory(I18N.getString("resource.pkg-background-image"))
+                .saveToFile(getConfig_BackgroundImageDarkAqua(params));
+
+        prepareDistributionXMLFile(params);
+
+        createResource(null, params)
+                .setCategory(I18N.getString("resource.post-install-script"))
+                .saveToFile(getConfig_Script(params));
+
+        return true;
+    }
+
+    // name of post-image script
+    private File getConfig_Script(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + "-post-image.sh");
+    }
+
+    private void patchCPLFile(File cpl) throws IOException {
+        String cplData = Files.readString(cpl.toPath());
+        String[] lines = cplData.split("\n");
+        try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(
+                cpl.toPath()))) {
+            int skip = 0;
+            // Used to skip Java.runtime bundle, since
+            // pkgbuild with --root will find two bundles app and Java runtime.
+            // We cannot generate component proprty list when using
+            // --component argument.
+            for (int i = 0; i < lines.length; i++) {
+                if (lines[i].trim().equals("<key>BundleIsRelocatable</key>")) {
+                    out.println(lines[i]);
+                    out.println("<false/>");
+                    i++;
+                } else if (lines[i].trim().equals("<key>ChildBundles</key>")) {
+                    ++skip;
+                } else if ((skip > 0) && lines[i].trim().equals("</array>")) {
+                    --skip;
+                } else {
+                    if (skip == 0) {
+                        out.println(lines[i]);
+                    }
+                }
+            }
+        }
+    }
+
+    // pkgbuild includes all components from "--root" and subfolders,
+    // so if we have app image in folder which contains other images, then they
+    // will be included as well. It does have "--filter" option which use regex
+    // to exclude files/folder, but it will overwrite default one which excludes
+    // based on doc "any .svn or CVS directories, and any .DS_Store files".
+    // So easy aproach will be to copy user provided app-image into temp folder
+    // if root path contains other files.
+    private String getRoot(Map<String, ? super Object> params,
+            File appLocation) throws IOException {
+        String root = appLocation.getParent() == null ?
+                "." : appLocation.getParent();
+        File rootDir = new File(root);
+        File[] list = rootDir.listFiles();
+        if (list != null) { // Should not happend
+            // We should only have app image and/or .DS_Store
+            if (list.length == 1) {
+                return root;
+            } else if (list.length == 2) {
+                // Check case with app image and .DS_Store
+                if (list[0].toString().toLowerCase().endsWith(".ds_store") ||
+                    list[1].toString().toLowerCase().endsWith(".ds_store")) {
+                    return root; // Only app image and .DS_Store
+                }
+            }
+        }
+
+        // Copy to new root
+        Path newRoot = Files.createTempDirectory(
+                TEMP_ROOT.fetchFrom(params).toPath(),
+                "root-");
+
+        IOUtils.copyRecursive(appLocation.toPath(),
+                newRoot.resolve(appLocation.getName()));
+
+        return newRoot.toString();
+    }
+
+    private File createPKG(Map<String, ? super Object> params,
+            File outdir, File appLocation) {
+        // generic find attempt
+        try {
+            File appPKG = getPackages_AppPackage(params);
+
+            String root = getRoot(params, appLocation);
+
+            // Generate default CPL file
+            File cpl = new File(CONFIG_ROOT.fetchFrom(params).getAbsolutePath()
+                    + File.separator + "cpl.plist");
+            ProcessBuilder pb = new ProcessBuilder("pkgbuild",
+                    "--root",
+                    root,
+                    "--install-location",
+                    MAC_INSTALL_DIR.fetchFrom(params),
+                    "--analyze",
+                    cpl.getAbsolutePath());
+
+            IOUtils.exec(pb);
+
+            patchCPLFile(cpl);
+
+            preparePackageScripts(params);
+
+            // build application package
+            pb = new ProcessBuilder("pkgbuild",
+                    "--root",
+                    root,
+                    "--install-location",
+                    MAC_INSTALL_DIR.fetchFrom(params),
+                    "--component-plist",
+                    cpl.getAbsolutePath(),
+                    "--scripts",
+                    SCRIPTS_DIR.fetchFrom(params).getAbsolutePath(),
+                    appPKG.getAbsolutePath());
+            IOUtils.exec(pb);
+
+            // build final package
+            File finalPKG = new File(outdir, INSTALLER_NAME.fetchFrom(params)
+                    + INSTALLER_SUFFIX.fetchFrom(params)
+                    + ".pkg");
+            outdir.mkdirs();
+
+            List<String> commandLine = new ArrayList<>();
+            commandLine.add("productbuild");
+
+            commandLine.add("--resources");
+            commandLine.add(CONFIG_ROOT.fetchFrom(params).getAbsolutePath());
+
+            // maybe sign
+            if (Optional.ofNullable(MacAppImageBuilder.
+                    SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) {
+                if (Platform.getMajorVersion() > 10 ||
+                    (Platform.getMajorVersion() == 10 &&
+                    Platform.getMinorVersion() >= 12)) {
+                    // we need this for OS X 10.12+
+                    Log.verbose(I18N.getString("message.signing.pkg"));
+                }
+
+                String signingIdentity =
+                        DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
+                if (signingIdentity != null) {
+                    commandLine.add("--sign");
+                    commandLine.add(signingIdentity);
+                }
+
+                String keychainName = SIGNING_KEYCHAIN.fetchFrom(params);
+                if (keychainName != null && !keychainName.isEmpty()) {
+                    commandLine.add("--keychain");
+                    commandLine.add(keychainName);
+                }
+            }
+
+            commandLine.add("--distribution");
+            commandLine.add(
+                    getConfig_DistributionXMLFile(params).getAbsolutePath());
+            commandLine.add("--package-path");
+            commandLine.add(PACKAGES_ROOT.fetchFrom(params).getAbsolutePath());
+
+            commandLine.add(finalPKG.getAbsolutePath());
+
+            pb = new ProcessBuilder(commandLine);
+            IOUtils.exec(pb);
+
+            return finalPKG;
+        } catch (Exception ignored) {
+            Log.verbose(ignored);
+            return null;
+        }
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+    // Implement Bundler
+    //////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String getName() {
+        return I18N.getString("pkg.bundler.name");
+    }
+
+    @Override
+    public String getID() {
+        return "pkg";
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws ConfigException {
+        try {
+            Objects.requireNonNull(params);
+
+            // run basic validation to ensure requirements are met
+            // we are not interested in return code, only possible exception
+            validateAppImageAndBundeler(params);
+
+            if (MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) == null) {
+                throw new ConfigException(
+                        I18N.getString("message.app-image-requires-identifier"),
+                        I18N.getString(
+                            "message.app-image-requires-identifier.advice"));
+            }
+
+            // reject explicitly set sign to true and no valid signature key
+            if (Optional.ofNullable(MacAppImageBuilder.
+                    SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) {
+                String signingIdentity =
+                        DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
+                if (signingIdentity == null) {
+                    throw new ConfigException(
+                            I18N.getString("error.explicit-sign-no-cert"),
+                            I18N.getString(
+                            "error.explicit-sign-no-cert.advice"));
+                }
+            }
+
+            // hdiutil is always available so there's no need
+            // to test for availability.
+
+            return true;
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) throws PackagerException {
+        return bundle(params, outputParentDir);
+    }
+
+    @Override
+    public boolean supported(boolean runtimeInstaller) {
+        return true;
+    }
+
+    @Override
+    public boolean isDefault() {
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/DMGsetup.scpt	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,38 @@
+tell application "Finder"
+  tell disk "DEPLOY_ACTUAL_VOLUME_NAME"
+    open
+    set current view of container window to icon view
+    set toolbar visible of container window to false
+    set statusbar visible of container window to false
+
+    -- size of window should match size of background
+    set the bounds of container window to {400, 100, 917, 380}
+
+    set theViewOptions to the icon view options of container window
+    set arrangement of theViewOptions to not arranged
+    set icon size of theViewOptions to 128
+    set background picture of theViewOptions to file ".background:background.png"
+
+    -- Create alias for install location
+    make new alias file at container window to DEPLOY_INSTALL_LOCATION with properties {name:"DEPLOY_INSTALL_NAME"}
+
+    set allTheFiles to the name of every item of container window
+    repeat with theFile in allTheFiles
+      set theFilePath to POSIX Path of theFile
+      if theFilePath is "/DEPLOY_APPLICATION_NAME.app"
+        -- Position application location
+        set position of item theFile of container window to {120, 130}
+      else if theFilePath is "/DEPLOY_INSTALL_NAME"
+        -- Position install location
+        set position of item theFile of container window to {390, 130}
+      else
+        -- Move all other files far enough to be not visible if user has "show hidden files" option set
+        set position of item theFile of container window to {1000, 130}
+      end
+    end repeat
+
+    update without registering applications
+    delay 5
+    close
+  end tell
+end tell
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/Info-lite.plist.template	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,37 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+  <key>LSMinimumSystemVersion</key>
+  <string>10.9</string>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>English</string>
+  <key>CFBundleAllowMixedLocalizations</key>
+  <true/>
+  <key>CFBundleExecutable</key>
+  <string>DEPLOY_LAUNCHER_NAME</string>
+  <key>CFBundleIconFile</key>
+  <string>DEPLOY_ICON_FILE</string>
+  <key>CFBundleIdentifier</key>
+  <string>DEPLOY_BUNDLE_IDENTIFIER</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>DEPLOY_BUNDLE_NAME</string>
+  <key>CFBundlePackageType</key>
+  <string>APPL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>DEPLOY_BUNDLE_SHORT_VERSION</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <!-- See https://developer.apple.com/app-store/categories/ for list of AppStore categories -->
+  <key>LSApplicationCategoryType</key>
+  <string>Unknown</string>
+  <key>CFBundleVersion</key>
+  <string>DEPLOY_BUNDLE_CFBUNDLE_VERSION</string>
+  <key>NSHumanReadableCopyright</key>
+  <string>DEPLOY_BUNDLE_COPYRIGHT</string>DEPLOY_FILE_ASSOCIATIONS
+  <key>NSHighResolutionCapable</key>
+  <string>true</string>
+ </dict>
+</plist>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacAppStore.entitlements	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+    <dict>
+        <key>com.apple.security.app-sandbox</key>
+        <true/>
+    </dict>
+</plist>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacAppStore_Inherit.entitlements	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+    <dict>
+        <key>com.apple.security.app-sandbox</key>
+        <true/>
+        <key>com.apple.security.inherit</key>
+        <true/>
+    </dict>
+</plist>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacResources.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,89 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+app.bundler.name=Mac Application Image
+store.bundler.name=Mac App Store Ready Bundler
+dmg.bundler.name=Mac DMG Package
+pkg.bundler.name=Mac PKG Package
+
+error.invalid-cfbundle-version=Invalid CFBundleVersion: [{0}]
+error.invalid-cfbundle-version.advice=Set a compatible 'appVersion' or set a 'mac.CFBundleVersion'. Valid versions are one to three integers separated by dots.
+error.explicit-sign-no-cert=Signature explicitly requested but no signing certificate specified
+error.explicit-sign-no-cert.advice=Either specify a valid cert in 'mac.signing-key-developer-id-app' or unset 'signBundle' or set 'signBundle' to false.
+error.must-sign-app-store=Mac App Store apps must be signed, and signing has been disabled by bundler configuration
+error.must-sign-app-store.advice=Either unset 'signBundle' or set 'signBundle' to true
+error.no-app-signing-key=No Mac App Store App Signing Key
+error.no-app-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
+error.no-pkg-signing-key=No Mac App Store Installer Signing Key
+error.no-pkg-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
+error.certificate.expired=Error: Certificate expired {0}
+error.no.xcode.signing=Xcode with command line developer tools is required for signing
+error.no.xcode.signing.advice=Install Xcode with command line developer tools.
+
+resource.bundle-config-file=Bundle config file
+resource.app-info-plist=Application Info.plist
+resource.runtime-info-plist=Java Runtime Info.plist
+resource.mac-app-store-entitlements=Mac App Store Entitlements
+resource.mac-app-store-inherit-entitlements=Mac App Store Inherit Entitlements
+resource.dmg-setup-script=DMG setup script
+resource.license-setup=License setup
+resource.dmg-background=dmg background
+resource.volume-icon=volume icon
+resource.post-install-script=script to run after application image is populated
+resource.pkg-preinstall-script=PKG preinstall script
+resource.pkg-postinstall-script=PKG postinstall script
+resource.pkg-background-image=pkg background image
+
+
+message.bundle-name-too-long-warning={0} is set to ''{1}'', which is longer than 16 characters. For a better Mac experience consider shortening it.
+message.null-classpath=Null app resources?
+message.preparing-info-plist=Preparing Info.plist: {0}.
+message.icon-not-icns= The specified icon "{0}" is not an ICNS file and will not be used. The default icon will be used in it's place.
+message.version-string-too-many-components=Version sting may have between 1 and 3 numbers: 1, 1.2, 1.2.3.
+message.version-string-first-number-not-zero=The first number in a CFBundleVersion cannot be zero or negative.
+message.version-string-no-negative-numbers=Negative numbers are not allowed in version strings.
+message.version-string-numbers-only=Version strings can consist of only numbers and up to two dots.
+message.creating-association-with-null-extension=Creating association with null extension.
+message.ignoring.symlink=Warning: codesign is skipping the symlink {0}.
+message.keychain.error=Error: unable to get keychain list.
+message.building-bundle=Building Mac App Store Package for {0}.
+message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists.
+message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists.
+message.app-image-requires-app-name=When using an external app image you must specify the app name.
+message.app-image-requires-app-name.advice=Set the app name via the -name CLI flag, the fx:application/@name ANT attribute, or via the 'appName' bundler argument.
+message.app-image-requires-identifier=Unable to extract identifier from app image.
+message.app-image-requires-identifier.advice=Use "--verbose" for extended error message or specify it via "--mac-package-identifier".
+message.building-dmg=Building DMG package for {0}.
+message.running-script=Running shell script on application image [{0}].
+message.preparing-dmg-setup=Preparing dmg setup: {0}.
+message.creating-dmg-file=Creating DMG file: {0}.
+message.dmg-cannot-be-overwritten=Dmg file exists ({0} and can not be removed.
+message.output-to-location=Result DMG installer for {0}: {1}.
+message.building-pkg=Building PKG package for {0}.
+message.preparing-scripts=Preparing package scripts.
+message.preparing-distribution-dist=Preparing distribution.dist: {0}.
+message.signing.pkg=Warning: For signing PKG, you might need to set "Always Trust" for your certificate using "Keychain Access" tool.
+message.setfile.dmg=Setting custom icon on DMG file skipped because 'SetFile' utility was not found. Installing Xcode with Command Line Tools should resolve this issue.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacResources_ja.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,89 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+app.bundler.name=Mac Application Image
+store.bundler.name=Mac App Store Ready Bundler
+dmg.bundler.name=Mac DMG Package
+pkg.bundler.name=Mac PKG Package
+
+error.invalid-cfbundle-version=Invalid CFBundleVersion: [{0}]
+error.invalid-cfbundle-version.advice=Set a compatible 'appVersion' or set a 'mac.CFBundleVersion'. Valid versions are one to three integers separated by dots.
+error.explicit-sign-no-cert=Signature explicitly requested but no signing certificate specified
+error.explicit-sign-no-cert.advice=Either specify a valid cert in 'mac.signing-key-developer-id-app' or unset 'signBundle' or set 'signBundle' to false.
+error.must-sign-app-store=Mac App Store apps must be signed, and signing has been disabled by bundler configuration
+error.must-sign-app-store.advice=Either unset 'signBundle' or set 'signBundle' to true
+error.no-app-signing-key=No Mac App Store App Signing Key
+error.no-app-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
+error.no-pkg-signing-key=No Mac App Store Installer Signing Key
+error.no-pkg-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
+error.certificate.expired=Error: Certificate expired {0}
+error.no.xcode.signing=Xcode with command line developer tools is required for signing
+error.no.xcode.signing.advice=Install Xcode with command line developer tools.
+
+resource.bundle-config-file=Bundle config file
+resource.app-info-plist=Application Info.plist
+resource.runtime-info-plist=Java Runtime Info.plist
+resource.mac-app-store-entitlements=Mac App Store Entitlements
+resource.mac-app-store-inherit-entitlements=Mac App Store Inherit Entitlements
+resource.dmg-setup-script=DMG setup script
+resource.license-setup=License setup
+resource.dmg-background=dmg background
+resource.volume-icon=volume icon
+resource.post-install-script=script to run after application image is populated
+resource.pkg-preinstall-script=PKG preinstall script
+resource.pkg-postinstall-script=PKG postinstall script
+resource.pkg-background-image=pkg background image
+
+
+message.bundle-name-too-long-warning={0} is set to ''{1}'', which is longer than 16 characters. For a better Mac experience consider shortening it.
+message.null-classpath=Null app resources?
+message.preparing-info-plist=Preparing Info.plist: {0}.
+message.icon-not-icns= The specified icon "{0}" is not an ICNS file and will not be used. The default icon will be used in it's place.
+message.version-string-too-many-components=Version sting may have between 1 and 3 numbers: 1, 1.2, 1.2.3.
+message.version-string-first-number-not-zero=The first number in a CFBundleVersion cannot be zero or negative.
+message.version-string-no-negative-numbers=Negative numbers are not allowed in version strings.
+message.version-string-numbers-only=Version strings can consist of only numbers and up to two dots.
+message.creating-association-with-null-extension=Creating association with null extension.
+message.ignoring.symlink=Warning: codesign is skipping the symlink {0}.
+message.keychain.error=Error: unable to get keychain list.
+message.building-bundle=Building Mac App Store Package for {0}.
+message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists.
+message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists.
+message.app-image-requires-app-name=When using an external app image you must specify the app name.
+message.app-image-requires-app-name.advice=Set the app name via the -name CLI flag, the fx:application/@name ANT attribute, or via the 'appName' bundler argument.
+message.app-image-requires-identifier=Unable to extract identifier from app image.
+message.app-image-requires-identifier.advice=Use "--verbose" for extended error message or specify it via "--mac-package-identifier".
+message.building-dmg=Building DMG package for {0}.
+message.running-script=Running shell script on application image [{0}].
+message.preparing-dmg-setup=Preparing dmg setup: {0}.
+message.creating-dmg-file=Creating DMG file: {0}.
+message.dmg-cannot-be-overwritten=Dmg file exists ({0} and can not be removed.
+message.output-to-location=Result DMG installer for {0}: {1}.
+message.building-pkg=Building PKG package for {0}.
+message.preparing-scripts=Preparing package scripts.
+message.preparing-distribution-dist=Preparing distribution.dist: {0}.
+message.signing.pkg=Warning: For signing PKG, you might need to set "Always Trust" for your certificate using "Keychain Access" tool.
+message.setfile.dmg=Setting custom icon on DMG file skipped because 'SetFile' utility was not found. Installing Xcode with Command Line Tools should resolve this issue.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacResources_zh_CN.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,89 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+app.bundler.name=Mac Application Image
+store.bundler.name=Mac App Store Ready Bundler
+dmg.bundler.name=Mac DMG Package
+pkg.bundler.name=Mac PKG Package
+
+error.invalid-cfbundle-version=Invalid CFBundleVersion: [{0}]
+error.invalid-cfbundle-version.advice=Set a compatible 'appVersion' or set a 'mac.CFBundleVersion'. Valid versions are one to three integers separated by dots.
+error.explicit-sign-no-cert=Signature explicitly requested but no signing certificate specified
+error.explicit-sign-no-cert.advice=Either specify a valid cert in 'mac.signing-key-developer-id-app' or unset 'signBundle' or set 'signBundle' to false.
+error.must-sign-app-store=Mac App Store apps must be signed, and signing has been disabled by bundler configuration
+error.must-sign-app-store.advice=Either unset 'signBundle' or set 'signBundle' to true
+error.no-app-signing-key=No Mac App Store App Signing Key
+error.no-app-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
+error.no-pkg-signing-key=No Mac App Store Installer Signing Key
+error.no-pkg-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
+error.certificate.expired=Error: Certificate expired {0}
+error.no.xcode.signing=Xcode with command line developer tools is required for signing
+error.no.xcode.signing.advice=Install Xcode with command line developer tools.
+
+resource.bundle-config-file=Bundle config file
+resource.app-info-plist=Application Info.plist
+resource.runtime-info-plist=Java Runtime Info.plist
+resource.mac-app-store-entitlements=Mac App Store Entitlements
+resource.mac-app-store-inherit-entitlements=Mac App Store Inherit Entitlements
+resource.dmg-setup-script=DMG setup script
+resource.license-setup=License setup
+resource.dmg-background=dmg background
+resource.volume-icon=volume icon
+resource.post-install-script=script to run after application image is populated
+resource.pkg-preinstall-script=PKG preinstall script
+resource.pkg-postinstall-script=PKG postinstall script
+resource.pkg-background-image=pkg background image
+
+
+message.bundle-name-too-long-warning={0} is set to ''{1}'', which is longer than 16 characters. For a better Mac experience consider shortening it.
+message.null-classpath=Null app resources?
+message.preparing-info-plist=Preparing Info.plist: {0}.
+message.icon-not-icns= The specified icon "{0}" is not an ICNS file and will not be used. The default icon will be used in it's place.
+message.version-string-too-many-components=Version sting may have between 1 and 3 numbers: 1, 1.2, 1.2.3.
+message.version-string-first-number-not-zero=The first number in a CFBundleVersion cannot be zero or negative.
+message.version-string-no-negative-numbers=Negative numbers are not allowed in version strings.
+message.version-string-numbers-only=Version strings can consist of only numbers and up to two dots.
+message.creating-association-with-null-extension=Creating association with null extension.
+message.ignoring.symlink=Warning: codesign is skipping the symlink {0}.
+message.keychain.error=Error: unable to get keychain list.
+message.building-bundle=Building Mac App Store Package for {0}.
+message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists.
+message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists.
+message.app-image-requires-app-name=When using an external app image you must specify the app name.
+message.app-image-requires-app-name.advice=Set the app name via the -name CLI flag, the fx:application/@name ANT attribute, or via the 'appName' bundler argument.
+message.app-image-requires-identifier=Unable to extract identifier from app image.
+message.app-image-requires-identifier.advice=Use "--verbose" for extended error message or specify it via "--mac-package-identifier".
+message.building-dmg=Building DMG package for {0}.
+message.running-script=Running shell script on application image [{0}].
+message.preparing-dmg-setup=Preparing dmg setup: {0}.
+message.creating-dmg-file=Creating DMG file: {0}.
+message.dmg-cannot-be-overwritten=Dmg file exists ({0} and can not be removed.
+message.output-to-location=Result DMG installer for {0}: {1}.
+message.building-pkg=Building PKG package for {0}.
+message.preparing-scripts=Preparing package scripts.
+message.preparing-distribution-dist=Preparing distribution.dist: {0}.
+message.signing.pkg=Warning: For signing PKG, you might need to set "Always Trust" for your certificate using "Keychain Access" tool.
+message.setfile.dmg=Setting custom icon on DMG file skipped because 'SetFile' utility was not found. Installing Xcode with Command Line Tools should resolve this issue.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/Runtime-Info.plist.template	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+        <key>CFBundleDevelopmentRegion</key>
+        <string>English</string>
+        <key>CFBundleExecutable</key>
+        <string>libjli.dylib</string>
+        <key>CFBundleIdentifier</key>
+        <string>CF_BUNDLE_IDENTIFIER</string>
+        <key>CFBundleInfoDictionaryVersion</key>
+        <string>7.0</string>
+        <key>CFBundleName</key>
+        <string>CF_BUNDLE_NAME</string>
+        <key>CFBundlePackageType</key>
+        <string>BNDL</string>
+        <key>CFBundleShortVersionString</key>
+        <string>CF_BUNDLE_SHORT_VERSION_STRING</string>
+        <key>CFBundleSignature</key>
+        <string>????</string>
+        <key>CFBundleVersion</key>
+        <string>CF_BUNDLE_VERSION</string>
+</dict>
+</plist>
Binary file src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/background_dmg.png has changed
Binary file src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/background_pkg.png has changed
Binary file src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/java.icns has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/lic_template.plist	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>LPic</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAAAAgAAAAAAAAAAAAQAAA==</data>
+			<key>ID</key>
+			<string>5000</string>
+			<key>Name</key>
+			<string></string>
+		</dict>
+	</array>
+	<key>STR#</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYPRW5nbGlzaCBkZWZhdWx0BUFncmVlCERpc2FncmVlBVByaW50B1NhdmUuLi56SWYgeW91IGFncmVlIHdpdGggdGhlIHRlcm1zIG9mIHRoaXMgbGljZW5zZSwgY2xpY2sgIkFncmVlIiB0byBhY2Nlc3MgdGhlIHNvZnR3YXJlLiAgSWYgeW91IGRvIG5vdCBhZ3JlZSwgcHJlc3MgIkRpc2FncmVlLiI=</data>
+			<key>ID</key>
+			<string>5000</string>
+			<key>Name</key>
+			<string>English buttons</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYHRGV1dHNjaAtBa3plcHRpZXJlbghBYmxlaG5lbgdEcnVja2VuClNpY2hlcm4uLi7nS2xpY2tlbiBTaWUgaW4g0kFremVwdGllcmVu0ywgd2VubiBTaWUgbWl0IGRlbiBCZXN0aW1tdW5nZW4gZGVzIFNvZnR3YXJlLUxpemVuenZlcnRyYWdzIGVpbnZlcnN0YW5kZW4gc2luZC4gRmFsbHMgbmljaHQsIGJpdHRlINJBYmxlaG5lbtMgYW5rbGlja2VuLiBTaWUga5pubmVuIGRpZSBTb2Z0d2FyZSBudXIgaW5zdGFsbGllcmVuLCB3ZW5uIFNpZSDSQWt6ZXB0aWVyZW7TIGFuZ2VrbGlja3QgaGFiZW4u</data>
+			<key>ID</key>
+			<string>5001</string>
+			<key>Name</key>
+			<string>German</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYHRW5nbGlzaAVBZ3JlZQhEaXNhZ3JlZQVQcmludAdTYXZlLi4ue0lmIHlvdSBhZ3JlZSB3aXRoIHRoZSB0ZXJtcyBvZiB0aGlzIGxpY2Vuc2UsIHByZXNzICJBZ3JlZSIgdG8gaW5zdGFsbCB0aGUgc29mdHdhcmUuICBJZiB5b3UgZG8gbm90IGFncmVlLCBwcmVzcyAiRGlzYWdyZWUiLg==</data>
+			<key>ID</key>
+			<string>5002</string>
+			<key>Name</key>
+			<string>English</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYHRXNwYZZvbAdBY2VwdGFyCk5vIGFjZXB0YXIISW1wcmltaXIKR3VhcmRhci4uLsBTaSBlc3SHIGRlIGFjdWVyZG8gY29uIGxvcyB0jnJtaW5vcyBkZSBlc3RhIGxpY2VuY2lhLCBwdWxzZSAiQWNlcHRhciIgcGFyYSBpbnN0YWxhciBlbCBzb2Z0d2FyZS4gRW4gZWwgc3VwdWVzdG8gZGUgcXVlIG5vIGVzdI4gZGUgYWN1ZXJkbyBjb24gbG9zIHSOcm1pbm9zIGRlIGVzdGEgbGljZW5jaWEsIHB1bHNlICJObyBhY2VwdGFyLiI=</data>
+			<key>ID</key>
+			<string>5003</string>
+			<key>Name</key>
+			<string>Spanish</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYIRnJhbo1haXMIQWNjZXB0ZXIHUmVmdXNlcghJbXByaW1lcg5FbnJlZ2lzdHJlci4uLrpTaSB2b3VzIGFjY2VwdGV6IGxlcyB0ZXJtZXMgZGUgbGEgcHKOc2VudGUgbGljZW5jZSwgY2xpcXVleiBzdXIgIkFjY2VwdGVyIiBhZmluIGQnaW5zdGFsbGVyIGxlIGxvZ2ljaWVsLiBTaSB2b3VzIG4nkHRlcyBwYXMgZCdhY2NvcmQgYXZlYyBsZXMgdGVybWVzIGRlIGxhIGxpY2VuY2UsIGNsaXF1ZXogc3VyICJSZWZ1c2VyIi4=</data>
+			<key>ID</key>
+			<string>5004</string>
+			<key>Name</key>
+			<string>French</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYISXRhbGlhbm8HQWNjZXR0bwdSaWZpdXRvBlN0YW1wYQtSZWdpc3RyYS4uLn9TZSBhY2NldHRpIGxlIGNvbmRpemlvbmkgZGkgcXVlc3RhIGxpY2VuemEsIGZhaSBjbGljIHN1ICJBY2NldHRvIiBwZXIgaW5zdGFsbGFyZSBpbCBzb2Z0d2FyZS4gQWx0cmltZW50aSBmYWkgY2xpYyBzdSAiUmlmaXV0byIu</data>
+			<key>ID</key>
+			<string>5005</string>
+			<key>Name</key>
+			<string>Italian</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYISmFwYW5lc2UKk6+I04K1gtyCtwyTr4jTgrWC3IK5gvEIiPON/IK3gukHlduRti4uLrSWe4Ncg3SDZ4NFg0eDQY5nl3CLlpH4jF+W8YLMj/CMj4LJk6+I04KzguqC6Y/qjYeCyYLNgUGDXIN0g2eDRYNHg0GC8INDg5ODWINngVuDi4K3gumCvYLfgsmBdZOviNOCtYLcgreBdoLwiZ+CtYLEgq2CvoKzgqKBQoFAk6+I04KzguqCyIKij+qNh4LJgs2BQYF1k6+I04K1gtyCuYLxgXaC8ImfgrWCxIKtgr6Cs4KigUI=</data>
+			<key>ID</key>
+			<string>5006</string>
+			<key>Name</key>
+			<string>Japanese</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYKTmVkZXJsYW5kcwJKYQNOZWUFUHJpbnQJQmV3YWFyLi4upEluZGllbiB1IGFra29vcmQgZ2FhdCBtZXQgZGUgdm9vcndhYXJkZW4gdmFuIGRlemUgbGljZW50aWUsIGt1bnQgdSBvcCAnSmEnIGtsaWtrZW4gb20gZGUgcHJvZ3JhbW1hdHV1ciB0ZSBpbnN0YWxsZXJlbi4gSW5kaWVuIHUgbmlldCBha2tvb3JkIGdhYXQsIGtsaWt0IHUgb3AgJ05lZScu</data>
+			<key>ID</key>
+			<string>5007</string>
+			<key>Name</key>
+			<string>Dutch</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYGU3ZlbnNrCEdvZGuKbm5zBkF2YppqcwhTa3JpdiB1dAhTcGFyYS4uLpNPbSBEdSBnb2Rrim5uZXIgbGljZW5zdmlsbGtvcmVuIGtsaWNrYSBwjCAiR29ka4pubnMiIGaaciBhdHQgaW5zdGFsbGVyYSBwcm9ncmFtcHJvZHVrdGVuLiBPbSBEdSBpbnRlIGdvZGuKbm5lciBsaWNlbnN2aWxsa29yZW4sIGtsaWNrYSBwjCAiQXZimmpzIi4=</data>
+			<key>ID</key>
+			<string>5008</string>
+			<key>Name</key>
+			<string>Swedish</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYRUG9ydHVndZBzLCBCcmFzaWwJQ29uY29yZGFyCURpc2NvcmRhcghJbXByaW1pcglTYWx2YXIuLi6MU2UgZXN0hyBkZSBhY29yZG8gY29tIG9zIHRlcm1vcyBkZXN0YSBsaWNlbo1hLCBwcmVzc2lvbmUgIkNvbmNvcmRhciIgcGFyYSBpbnN0YWxhciBvIHNvZnR3YXJlLiBTZSBui28gZXN0hyBkZSBhY29yZG8sIHByZXNzaW9uZSAiRGlzY29yZGFyIi4=</data>
+			<key>ID</key>
+			<string>5009</string>
+			<key>Name</key>
+			<string>Brazilian Portuguese</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYSU2ltcGxpZmllZCBDaGluZXNlBM2s0uIGsrvNrNLiBLTy06EGtOa0oqGtVMjnufvE+s2s0uKxvtDtv8nQrdLptcTM9b/uo6zH67C0obDNrNLiobHAtLCy17C0y8jtvP6ho8jnufvE+rK7zazS4qOsx+uwtKGwsrvNrNLiobGhow==</data>
+			<key>ID</key>
+			<string>5010</string>
+			<key>Name</key>
+			<string>Simplified Chinese</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYTVHJhZGl0aW9uYWwgQ2hpbmVzZQSmULdOBqSjplC3TgSmQ6ZMBsB4pnOhS1CmcKpHsXqmULdOpbuzXKVpw9K4zKq6sfi02qFBvdCr9qGnplC3TqGopUimd7jLs27F6aFDpnCqR6SjplC3TqFBvdCr9qGnpKOmULdOoaihQw==</data>
+			<key>ID</key>
+			<string>5011</string>
+			<key>Name</key>
+			<string>Traditional Chinese</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYFRGFuc2sERW5pZwVVZW5pZwdVZHNrcml2CkFya2l2ZXIuLi6YSHZpcyBkdSBhY2NlcHRlcmVyIGJldGluZ2Vsc2VybmUgaSBsaWNlbnNhZnRhbGVuLCBza2FsIGR1IGtsaWtrZSBwjCDSRW5pZ9MgZm9yIGF0IGluc3RhbGxlcmUgc29mdHdhcmVuLiBLbGlrIHCMINJVZW5pZ9MgZm9yIGF0IGFubnVsbGVyZSBpbnN0YWxsZXJpbmdlbi4=</data>
+			<key>ID</key>
+			<string>5012</string>
+			<key>Name</key>
+			<string>Danish</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYFU3VvbWkISHl2imtzeW4KRW4gaHl2imtzeQdUdWxvc3RhCVRhbGxlbm5hyW9IeXaKa3N5IGxpc2Vuc3Npc29waW11a3NlbiBlaGRvdCBvc29pdHRhbWFsbGEg1Uh5doprc3nVLiBKb3MgZXQgaHl2imtzeSBzb3BpbXVrc2VuIGVodG9qYSwgb3NvaXRhINVFbiBoeXaKa3N51S4=</data>
+			<key>ID</key>
+			<string>5013</string>
+			<key>Name</key>
+			<string>Finnish</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYRRnJhbo1haXMgY2FuYWRpZW4IQWNjZXB0ZXIHUmVmdXNlcghJbXByaW1lcg5FbnJlZ2lzdHJlci4uLrpTaSB2b3VzIGFjY2VwdGV6IGxlcyB0ZXJtZXMgZGUgbGEgcHKOc2VudGUgbGljZW5jZSwgY2xpcXVleiBzdXIgIkFjY2VwdGVyIiBhZmluIGQnaW5zdGFsbGVyIGxlIGxvZ2ljaWVsLiBTaSB2b3VzIG4nkHRlcyBwYXMgZCdhY2NvcmQgYXZlYyBsZXMgdGVybWVzIGRlIGxhIGxpY2VuY2UsIGNsaXF1ZXogc3VyICJSZWZ1c2VyIi4=</data>
+			<key>ID</key>
+			<string>5014</string>
+			<key>Name</key>
+			<string>French Canadian</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYGS29yZWFuBLW/wMcJtb/AxyC+yMfUBsfBuLDGrgfA+sDlLi4ufrvnv+sgsOi+4LytwMcgs7u/67+hILW/wMfHz7jpLCAitb/AxyIgtNzD37imILStt68gvNLHwcauv/6+7rimILyzxKHHz73KvcO/wC4gtb/Ax8fPwfYgvsq0wrTZuOksICK1v8DHIL7Ix9QiILTcw9+4piC0qbijvcq9w7/ALg==</data>
+			<key>ID</key>
+			<string>5015</string>
+			<key>Name</key>
+			<string>Korean</string>
+		</dict>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAYFTm9yc2sERW5pZwlJa2tlIGVuaWcIU2tyaXYgdXQKQXJraXZlci4uLqNIdmlzIERlIGVyIGVuaWcgaSBiZXN0ZW1tZWxzZW5lIGkgZGVubmUgbGlzZW5zYXZ0YWxlbiwga2xpa2tlciBEZSBwjCAiRW5pZyIta25hcHBlbiBmb3IgjCBpbnN0YWxsZXJlIHByb2dyYW12YXJlbi4gSHZpcyBEZSBpa2tlIGVyIGVuaWcsIGtsaWtrZXIgRGUgcIwgIklra2UgZW5pZyIu</data>
+			<key>ID</key>
+			<string>5016</string>
+			<key>Name</key>
+			<string>Norwegian</string>
+		</dict>
+	</array>
+	<key>TEXT</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>APPLICATION_LICENSE_TEXT</data>
+			<key>ID</key>
+			<string>5000</string>
+			<key>Name</key>
+			<string>English SLA</string>
+		</dict>
+	</array>
+	<key>TMPL</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>E0RlZmF1bHQgTGFuZ3VhZ2UgSUREV1JEBUNvdW50T0NOVAQqKioqTFNUQwtzeXMgbGFuZyBJRERXUkQebG9jYWwgcmVzIElEIChvZmZzZXQgZnJvbSA1MDAwRFdSRBAyLWJ5dGUgbGFuZ3VhZ2U/RFdSRAQqKioqTFNURQ==</data>
+			<key>ID</key>
+			<string>128</string>
+			<key>Name</key>
+			<string>LPic</string>
+		</dict>
+	</array>
+	<key>plst</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0050</string>
+			<key>Data</key>
+			<data>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</data>
+			<key>ID</key>
+			<string>0</string>
+			<key>Name</key>
+			<string></string>
+		</dict>
+	</array>
+	<key>styl</key>
+	<array>
+		<dict>
+			<key>Attributes</key>
+			<string>0x0000</string>
+			<key>Data</key>
+			<data>AAMAAAAAAAwACQAUAAAAAAAAAAAAAAAAACcADAAJABQBAAAAAAAAAAAAAAAAKgAMAAkAFAAAAAAAAAAAAAA=</data>
+			<key>ID</key>
+			<string>5000</string>
+			<key>Name</key>
+			<string>English SLA</string>
+		</dict>
+	</array>
+</dict>
+</plist>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/postinstall.template	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,7 @@
+#!/usr/bin/env sh
+
+chown root:wheel "INSTALL_LOCATION"
+chmod a+rX "INSTALL_LOCATION"
+chmod +r "APP_LOCATION/"*.jar
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/preinstall.template	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,8 @@
+#!/usr/bin/env sh
+
+if [ ! -d "INSTALL_LOCATION" ]
+then
+    mkdir -p "INSTALL_LOCATION"
+fi
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/classes/module-info.java.extra	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+
+provides jdk.incubator.jpackage.internal.Bundler with
+    jdk.incubator.jpackage.internal.MacAppBundler,
+    jdk.incubator.jpackage.internal.MacAppStoreBundler,
+    jdk.incubator.jpackage.internal.MacDmgBundler,
+    jdk.incubator.jpackage.internal.MacPkgBundler;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/native/jpackageapplauncher/main.m	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012, 2019, 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+#include <dlfcn.h>
+#include <unistd.h>
+
+typedef bool (*start_launcher)(int argc, char* argv[]);
+typedef void (*stop_launcher)();
+
+int main(int argc, char *argv[]) {
+#if !__has_feature(objc_arc)
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+#endif
+
+    int result = 1;
+
+    @try {
+        setlocale(LC_ALL, "en_US.utf8");
+
+        NSBundle *mainBundle = [NSBundle mainBundle];
+        NSString *mainBundlePath = [mainBundle bundlePath];
+        NSString *libraryName = [mainBundlePath stringByAppendingPathComponent:@"Contents/MacOS/libapplauncher.dylib"];
+
+        void* library = dlopen([libraryName UTF8String], RTLD_LAZY);
+
+        if (library == NULL) {
+            NSLog(@"%@ not found.\n", libraryName);
+        }
+
+        if (library != NULL) {
+            start_launcher start =
+                    (start_launcher)dlsym(library, "start_launcher");
+            stop_launcher stop =
+                    (stop_launcher)dlsym(library, "stop_launcher");
+
+            if (start != NULL && stop != NULL) {
+                if (start(argc, argv) == true) {
+                    result = 0;
+                    stop();
+                }
+            } else if (start == NULL) {
+                NSLog(@"start_launcher not found in %@.\n", libraryName);
+            } else {
+                NSLog(@"stop_launcher not found in %@.\n", libraryName);
+            }
+            dlclose(library);
+        }
+    } @catch (NSException *exception) {
+        NSLog(@"%@: %@", exception, [exception callStackSymbols]);
+        result = 1;
+    }
+
+#if !__has_feature(objc_arc)
+    [pool drain];
+#endif
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/native/libapplauncher/MacPlatform.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef MACPLATFORM_H
+#define MACPLATFORM_H
+
+#include "Platform.h"
+#include "PosixPlatform.h"
+
+class MacPlatform : virtual public Platform, PosixPlatform {
+private:
+    bool UsePListForConfigFile();
+
+protected:
+    virtual TString getTmpDirString();
+
+public:
+    MacPlatform(void);
+    virtual ~MacPlatform(void);
+
+public:
+    virtual void ShowMessage(TString title, TString description);
+    virtual void ShowMessage(TString description);
+
+    virtual TCHAR* ConvertStringToFileSystemString(
+            TCHAR* Source, bool &release);
+    virtual TCHAR* ConvertFileSystemStringToString(
+            TCHAR* Source, bool &release);
+
+    virtual TString GetPackageRootDirectory();
+    virtual TString GetAppDataDirectory();
+    virtual TString GetBundledJavaLibraryFileName(TString RuntimePath);
+    virtual TString GetAppName();
+
+    TString GetPackageAppDirectory();
+    TString GetPackageLauncherDirectory();
+    TString GetPackageRuntimeBinDirectory();
+
+    virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
+    virtual TString GetModuleFileName();
+
+    virtual bool IsMainThread();
+    virtual TPlatformNumber GetMemorySize();
+
+    virtual std::map<TString, TString> GetKeys();
+};
+
+
+#endif // MACPLATFORM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/native/libapplauncher/MacPlatform.mm	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "Platform.h"
+
+#include "MacPlatform.h"
+#include "Helpers.h"
+#include "Package.h"
+#include "PropertyFile.h"
+#include "IniFile.h"
+
+#include <sys/sysctl.h>
+#include <pthread.h>
+#include <vector>
+#include <signal.h>
+#include <mach-o/dyld.h>
+
+#import <Foundation/Foundation.h>
+#import <AppKit/NSRunningApplication.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreFoundation/CFString.h>
+
+#ifdef __OBJC__
+#import <Cocoa/Cocoa.h>
+#endif //__OBJC__
+
+#define MAC_JPACKAGE_TMP_DIR \
+        "/Library/Application Support/Java/JPackage/tmp"
+
+NSString* StringToNSString(TString Value) {
+    NSString* result = [NSString stringWithCString : Value.c_str()
+            encoding : [NSString defaultCStringEncoding]];
+    return result;
+}
+
+FileSystemStringToString::FileSystemStringToString(const TCHAR* value) {
+    bool release = false;
+    PlatformString lvalue = PlatformString(value);
+    Platform& platform = Platform::GetInstance();
+    TCHAR* buffer = platform.ConvertFileSystemStringToString(lvalue, release);
+    FData = buffer;
+
+    if (buffer != NULL && release == true) {
+        delete[] buffer;
+    }
+}
+
+FileSystemStringToString::operator TString() {
+    return FData;
+}
+
+StringToFileSystemString::StringToFileSystemString(const TString &value) {
+    FRelease = false;
+    PlatformString lvalue = PlatformString(value);
+    Platform& platform = Platform::GetInstance();
+    FData = platform.ConvertStringToFileSystemString(lvalue, FRelease);
+}
+
+StringToFileSystemString::~StringToFileSystemString() {
+    if (FRelease == true) {
+        delete[] FData;
+    }
+}
+
+StringToFileSystemString::operator TCHAR* () {
+    return FData;
+}
+
+MacPlatform::MacPlatform(void) : Platform(), PosixPlatform() {
+}
+
+MacPlatform::~MacPlatform(void) {
+}
+
+TString MacPlatform::GetPackageAppDirectory() {
+    return FilePath::IncludeTrailingSeparator(
+            GetPackageRootDirectory()) + _T("app");
+}
+
+TString MacPlatform::GetPackageLauncherDirectory() {
+    return FilePath::IncludeTrailingSeparator(
+            GetPackageRootDirectory()) + _T("MacOS");
+}
+
+TString MacPlatform::GetPackageRuntimeBinDirectory() {
+    return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory()) +
+            _T("runtime/Contents/Home/bin");
+}
+
+bool MacPlatform::UsePListForConfigFile() {
+    return FilePath::FileExists(GetConfigFileName()) == false;
+}
+
+void MacPlatform::ShowMessage(TString Title, TString Description) {
+    NSString *ltitle = StringToNSString(Title);
+    NSString *ldescription = StringToNSString(Description);
+
+    NSLog(@"%@:%@", ltitle, ldescription);
+}
+
+void MacPlatform::ShowMessage(TString Description) {
+    TString appname = GetModuleFileName();
+    appname = FilePath::ExtractFileName(appname);
+    ShowMessage(appname, Description);
+}
+
+TString MacPlatform::getTmpDirString() {
+    return TString(MAC_JPACKAGE_TMP_DIR);
+}
+
+TCHAR* MacPlatform::ConvertStringToFileSystemString(TCHAR* Source,
+        bool &release) {
+    TCHAR* result = NULL;
+    release = false;
+    CFStringRef StringRef = CFStringCreateWithCString(kCFAllocatorDefault,
+            Source, kCFStringEncodingUTF8);
+
+    if (StringRef != NULL) {
+        @ try {
+            CFIndex length =
+                    CFStringGetMaximumSizeOfFileSystemRepresentation(StringRef);
+            result = new char[length + 1];
+            if (result != NULL) {
+                if (CFStringGetFileSystemRepresentation(StringRef,
+                        result, length)) {
+                    release = true;
+                } else {
+                    delete[] result;
+                    result = NULL;
+                }
+            }
+        }
+        @finally
+        {
+            CFRelease(StringRef);
+        }
+    }
+
+    return result;
+}
+
+TCHAR* MacPlatform::ConvertFileSystemStringToString(TCHAR* Source,
+        bool &release) {
+    TCHAR* result = NULL;
+    release = false;
+    CFStringRef StringRef = CFStringCreateWithFileSystemRepresentation(
+            kCFAllocatorDefault, Source);
+
+    if (StringRef != NULL) {
+        @ try {
+            CFIndex length = CFStringGetLength(StringRef);
+
+            if (length > 0) {
+                CFIndex maxSize = CFStringGetMaximumSizeForEncoding(
+                        length, kCFStringEncodingUTF8);
+
+                result = new char[maxSize + 1];
+                if (result != NULL) {
+                    if (CFStringGetCString(StringRef, result, maxSize,
+                            kCFStringEncodingUTF8) == true) {
+                        release = true;
+                    } else {
+                        delete[] result;
+                        result = NULL;
+                    }
+                }
+            }
+        }
+        @finally
+        {
+            CFRelease(StringRef);
+        }
+    }
+
+    return result;
+}
+
+TString MacPlatform::GetPackageRootDirectory() {
+    NSBundle *mainBundle = [NSBundle mainBundle];
+    NSString *mainBundlePath = [mainBundle bundlePath];
+    NSString *contentsPath =
+            [mainBundlePath stringByAppendingString : @"/Contents"];
+    TString result = [contentsPath UTF8String];
+    return result;
+}
+
+TString MacPlatform::GetAppDataDirectory() {
+    TString result;
+    NSArray *paths = NSSearchPathForDirectoriesInDomains(
+            NSApplicationSupportDirectory, NSUserDomainMask, YES);
+    NSString *applicationSupportDirectory = [paths firstObject];
+    result = [applicationSupportDirectory UTF8String];
+    return result;
+}
+
+TString MacPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) {
+    TString result;
+
+    // first try lib/, then lib/jli
+    result = FilePath::IncludeTrailingSeparator(RuntimePath) +
+            _T("Contents/Home/lib/libjli.dylib");
+
+    if (FilePath::FileExists(result) == false) {
+        result = FilePath::IncludeTrailingSeparator(RuntimePath) +
+                _T("Contents/Home/lib/jli/libjli.dylib");
+
+        if (FilePath::FileExists(result) == false) {
+            // cannot find
+            NSLog(@"Cannot find libjli.dysym!");
+            result = _T("");
+        }
+    }
+
+    return result;
+}
+
+TString MacPlatform::GetAppName() {
+    NSString *appName = [[NSProcessInfo processInfo] processName];
+    TString result = [appName UTF8String];
+    return result;
+}
+
+void PosixProcess::Cleanup() {
+    if (FOutputHandle != 0) {
+        close(FOutputHandle);
+        FOutputHandle = 0;
+    }
+
+    if (FInputHandle != 0) {
+        close(FInputHandle);
+        FInputHandle = 0;
+    }
+
+    sigaction(SIGINT, &savintr, (struct sigaction *) 0);
+    sigaction(SIGQUIT, &savequit, (struct sigaction *) 0);
+    sigprocmask(SIG_SETMASK, &saveblock, (sigset_t *) 0);
+}
+
+#define PIPE_READ 0
+#define PIPE_WRITE 1
+
+bool PosixProcess::Execute(const TString Application,
+        const std::vector<TString> Arguments, bool AWait) {
+    bool result = false;
+
+    if (FRunning == false) {
+        FRunning = true;
+
+        int handles[2];
+
+        if (pipe(handles) == -1) {
+            return false;
+        }
+
+        struct sigaction sa;
+        sa.sa_handler = SIG_IGN;
+        sigemptyset(&sa.sa_mask);
+        sa.sa_flags = 0;
+        sigemptyset(&savintr.sa_mask);
+        sigemptyset(&savequit.sa_mask);
+        sigaction(SIGINT, &sa, &savintr);
+        sigaction(SIGQUIT, &sa, &savequit);
+        sigaddset(&sa.sa_mask, SIGCHLD);
+        sigprocmask(SIG_BLOCK, &sa.sa_mask, &saveblock);
+
+        FChildPID = fork();
+
+        // PID returned by vfork is 0 for the child process and the
+        // PID of the child process for the parent.
+        if (FChildPID == -1) {
+            // Error
+            TString message = PlatformString::Format(
+                    _T("Error: Unable to create process %s"),
+                    Application.data());
+            throw Exception(message);
+        } else if (FChildPID == 0) {
+            Cleanup();
+            TString command = Application;
+
+            for (std::vector<TString>::const_iterator iterator =
+                    Arguments.begin(); iterator != Arguments.end();
+                    iterator++) {
+                command += TString(_T(" ")) + *iterator;
+            }
+#ifdef DEBUG
+            printf("%s\n", command.data());
+#endif // DEBUG
+
+            dup2(handles[PIPE_READ], STDIN_FILENO);
+            dup2(handles[PIPE_WRITE], STDOUT_FILENO);
+
+            close(handles[PIPE_READ]);
+            close(handles[PIPE_WRITE]);
+
+            execl("/bin/sh", "sh", "-c", command.data(), (char *) 0);
+
+            _exit(127);
+        } else {
+            FOutputHandle = handles[PIPE_READ];
+            FInputHandle = handles[PIPE_WRITE];
+
+            if (AWait == true) {
+                ReadOutput();
+                Wait();
+                Cleanup();
+                FRunning = false;
+                result = true;
+            } else {
+                result = true;
+            }
+        }
+    }
+
+    return result;
+}
+
+void AppendPListArrayToIniFile(NSDictionary *infoDictionary,
+        IniFile *result, TString Section) {
+    NSString *sectionKey =
+            [NSString stringWithUTF8String : PlatformString(Section).toMultibyte()];
+    NSDictionary *array = [infoDictionary objectForKey : sectionKey];
+
+    for (id option in array) {
+        if ([option isKindOfClass : [NSString class]]) {
+            TString arg = [option UTF8String];
+
+            TString name;
+            TString value;
+
+            if (Helpers::SplitOptionIntoNameValue(arg, name, value) == true) {
+                result->Append(Section, name, value);
+            }
+        }
+    }
+}
+
+void AppendPListDictionaryToIniFile(NSDictionary *infoDictionary,
+        IniFile *result, TString Section, bool FollowSection = true) {
+    NSDictionary *dictionary = NULL;
+
+    if (FollowSection == true) {
+        NSString *sectionKey = [NSString stringWithUTF8String : PlatformString(
+                Section).toMultibyte()];
+        dictionary = [infoDictionary objectForKey : sectionKey];
+    } else {
+        dictionary = infoDictionary;
+    }
+
+    for (id key in dictionary) {
+        id option = [dictionary valueForKey : key];
+
+        if ([key isKindOfClass : [NSString class]] &&
+                [option isKindOfClass : [NSString class]]) {
+            TString name = [key UTF8String];
+            TString value = [option UTF8String];
+            result->Append(Section, name, value);
+        }
+    }
+}
+
+// Convert parts of the info.plist to the INI format the rest of the jpackage
+// uses unless a jpackage config file exists.
+ISectionalPropertyContainer* MacPlatform::GetConfigFile(TString FileName) {
+    IniFile* result = new IniFile();
+    if (result == NULL) {
+        return NULL;
+    }
+
+    if (UsePListForConfigFile() == false) {
+        result->LoadFromFile(FileName);
+    } else {
+        NSBundle *mainBundle = [NSBundle mainBundle];
+        NSDictionary *infoDictionary = [mainBundle infoDictionary];
+        std::map<TString, TString> keys = GetKeys();
+
+        // JPackage options.
+        AppendPListDictionaryToIniFile(infoDictionary, result,
+                keys[CONFIG_SECTION_APPLICATION], false);
+
+        // jvmargs
+        AppendPListArrayToIniFile(infoDictionary, result,
+                keys[CONFIG_SECTION_JAVAOPTIONS]);
+
+        // Generate AppCDS Cache
+        AppendPListDictionaryToIniFile(infoDictionary, result,
+                keys[CONFIG_SECTION_APPCDSJAVAOPTIONS]);
+        AppendPListDictionaryToIniFile(infoDictionary, result,
+                keys[CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS]);
+
+        // args
+        AppendPListArrayToIniFile(infoDictionary, result,
+                keys[CONFIG_SECTION_ARGOPTIONS]);
+    }
+
+    return result;
+}
+
+TString GetModuleFileNameOSX() {
+    Dl_info module_info;
+    if (dladdr(reinterpret_cast<void*> (GetModuleFileNameOSX),
+            &module_info) == 0) {
+        // Failed to find the symbol we asked for.
+        return std::string();
+    }
+    return TString(module_info.dli_fname);
+}
+
+TString MacPlatform::GetModuleFileName() {
+    TString result;
+    DynamicBuffer<TCHAR> buffer(MAX_PATH);
+    uint32_t size = buffer.GetSize();
+
+    if (_NSGetExecutablePath(buffer.GetData(), &size) == 0) {
+        result = FileSystemStringToString(buffer.GetData());
+    }
+
+    return result;
+}
+
+bool MacPlatform::IsMainThread() {
+    bool result = (pthread_main_np() == 1);
+    return result;
+}
+
+TPlatformNumber MacPlatform::GetMemorySize() {
+    unsigned long long memory = [[NSProcessInfo processInfo] physicalMemory];
+
+    // Convert from bytes to megabytes.
+    TPlatformNumber result = memory / 1048576;
+
+    return result;
+}
+
+std::map<TString, TString> MacPlatform::GetKeys() {
+    std::map<TString, TString> keys;
+
+    if (UsePListForConfigFile() == false) {
+        return Platform::GetKeys();
+    } else {
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_VERSION,
+                _T("app.version")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINJAR_KEY,
+                _T("JavaMainJarName")));
+        keys.insert(std::map<TString,
+                TString>::value_type(CONFIG_MAINMODULE_KEY,
+                _T("JavaMainModuleName")));
+        keys.insert(std::map<TString, TString>::value_type(
+                CONFIG_MAINCLASSNAME_KEY, _T("JavaMainClassName")));
+        keys.insert(std::map<TString, TString>::value_type(
+                CONFIG_CLASSPATH_KEY, _T("JavaAppClasspath")));
+        keys.insert(std::map<TString, TString>::value_type(APP_NAME_KEY,
+                _T("CFBundleName")));
+        keys.insert(std::map<TString, TString>::value_type(JAVA_RUNTIME_KEY,
+                _T("JavaRuntime")));
+        keys.insert(std::map<TString,
+                TString>::value_type(JPACKAGE_APP_DATA_DIR,
+                _T("CFBundleIdentifier")));
+
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_SPLASH_KEY,
+                _T("app.splash")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_MEMORY,
+                _T("app.memory")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_DEBUG,
+                _T("app.debug")));
+        keys.insert(std::map<TString, TString>::value_type(
+                CONFIG_APPLICATION_INSTANCE, _T("app.application.instance")));
+
+        keys.insert(std::map<TString, TString>::value_type(
+                CONFIG_SECTION_APPLICATION, _T("Application")));
+        keys.insert(std::map<TString, TString>::value_type(
+                CONFIG_SECTION_JAVAOPTIONS, _T("JavaOptions")));
+        keys.insert(std::map<TString, TString>::value_type(
+                CONFIG_SECTION_APPCDSJAVAOPTIONS, _T("AppCDSJavaOptions")));
+        keys.insert(std::map<TString, TString>::value_type(
+                CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS,
+                _T("AppCDSGenerateCacheJavaOptions")));
+        keys.insert(std::map<TString, TString>::value_type(
+                CONFIG_SECTION_ARGOPTIONS, _T("ArgOptions")));
+    }
+
+    return keys;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/macosx/native/libapplauncher/PlatformDefs.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef PLATFORM_DEFS_H
+#define PLATFORM_DEFS_H
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <libgen.h>
+#include <string>
+
+using namespace std;
+
+#ifndef MAC
+#define MAC
+#endif
+
+#define _T(x) x
+
+typedef char TCHAR;
+typedef std::string TString;
+#define StringLength strlen
+
+typedef unsigned long DWORD;
+
+#define TRAILING_PATHSEPARATOR '/'
+#define BAD_TRAILING_PATHSEPARATOR '\\'
+#define PATH_SEPARATOR ':'
+#define BAD_PATH_SEPARATOR ';'
+#define MAX_PATH 1000
+
+typedef long TPlatformNumber;
+typedef pid_t TProcessID;
+
+#define HMODULE void*
+
+typedef void* Module;
+typedef void* Procedure;
+
+
+// StringToFileSystemString is a stack object. It's usage is
+// simply inline to convert a
+// TString to a file system string. Example:
+//
+// return dlopen(StringToFileSystemString(FileName), RTLD_LAZY);
+//
+class StringToFileSystemString {
+    // Prohibit Heap-Based StringToFileSystemString
+private:
+    static void *operator new(size_t size);
+    static void operator delete(void *ptr);
+
+private:
+    TCHAR* FData;
+    bool FRelease;
+
+public:
+    StringToFileSystemString(const TString &value);
+    ~StringToFileSystemString();
+
+    operator TCHAR* ();
+};
+
+
+// FileSystemStringToString is a stack object. It's usage is
+// simply inline to convert a
+// file system string to a TString. Example:
+//
+// DynamicBuffer<TCHAR> buffer(MAX_PATH);
+// if (readlink("/proc/self/exe", buffer.GetData(), MAX_PATH) != -1)
+//    result = FileSystemStringToString(buffer.GetData());
+//
+class FileSystemStringToString {
+    // Prohibit Heap-Based FileSystemStringToString
+private:
+    static void *operator new(size_t size);
+    static void operator delete(void *ptr);
+
+private:
+    TString FData;
+
+public:
+    FileSystemStringToString(const TCHAR* value);
+
+    operator TString ();
+};
+
+#endif // PLATFORM_DEFS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/ToolProviderFactory.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2019, 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
+ * 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.incubator.jpackage;
+
+import jdk.incubator.jpackage.internal.JPackageToolProvider;
+import java.io.PrintWriter;
+import java.util.Optional;
+import java.util.spi.ToolProvider;
+
+/**
+ * A factory class to obtain a {@linkplain ToolProvider tool provider}
+ * for the incubating {@code jpackage} tool.
+ * 
+ * It is planned to implement {@code jpackage} tool as a service provider
+ * to {@link ToolProvider} in a future release at which point
+ * {@link ToolProvider#findFirst} can be used to look up jpackage tool.
+ *
+ * @since   14
+ */
+
+public class ToolProviderFactory { 
+
+    private static ToolProvider provider = new JPackageToolProvider();
+
+    // Prevent creating an instance of this class
+    private ToolProviderFactory() {
+    }
+
+    /**
+     * Returns an {@link Optional} containing the {@code ToolProvider}
+     * if the given toolname is "jpackage". Returns an empty
+     * {@code Optional} if the given toolname is not "jpackage".
+     *
+     * @param   toolname {@code String} name of tool to look for.
+     * @return  an {@link Optional} containing the {@code ToolPovider}
+     *
+     * @since 14
+     */
+    public static Optional<ToolProvider> findFirst(String toolName) {
+        if ("jpackage".equals(toolName)) {
+            return Optional.of(provider);
+        } else {
+            return Optional.empty();
+        }
+    } 
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractAppImageBuilder.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2015, 2019, 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.incubator.jpackage.internal;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.ArrayList;
+
+import jdk.incubator.jpackage.internal.resources.ResourceLocator;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+/*
+ * AbstractAppImageBuilder
+ *     This is sub-classed by each of the platform dependent AppImageBuilder
+ * classes, and contains resource processing code common to all platforms.
+ */
+
+public abstract class AbstractAppImageBuilder {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MainResources");
+
+    private final Path root;
+
+    public AbstractAppImageBuilder(Map<String, Object> unused, Path root) {
+        this.root = root;
+    }
+
+    public InputStream getResourceAsStream(String name) {
+        return ResourceLocator.class.getResourceAsStream(name);
+    }
+
+    public abstract void prepareApplicationFiles(
+            Map<String, ? super Object> params) throws IOException;
+    public abstract void prepareJreFiles(
+            Map<String, ? super Object> params) throws IOException;
+    public abstract Path getAppDir();
+    public abstract Path getAppModsDir();
+
+    public Path getRuntimeRoot() {
+        return this.root;
+    }
+
+    protected void copyEntry(Path appDir, File srcdir, String fname)
+            throws IOException {
+        Path dest = appDir.resolve(fname);
+        Files.createDirectories(dest.getParent());
+        File src = new File(srcdir, fname);
+        if (src.isDirectory()) {
+            IOUtils.copyRecursive(src.toPath(), dest);
+        } else {
+            Files.copy(src.toPath(), dest);
+        }
+    }
+
+    public void writeCfgFile(Map<String, ? super Object> params,
+            File cfgFileName) throws IOException {
+        cfgFileName.getParentFile().mkdirs();
+        cfgFileName.delete();
+        File mainJar = JLinkBundlerHelper.getMainJar(params);
+        ModFile.ModType mainJarType = ModFile.ModType.Unknown;
+
+        if (mainJar != null) {
+            mainJarType = new ModFile(mainJar).getModType();
+        }
+
+        String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
+
+        try (PrintStream out = new PrintStream(cfgFileName)) {
+
+            out.println("[Application]");
+            out.println("app.name=" + APP_NAME.fetchFrom(params));
+            out.println("app.version=" + VERSION.fetchFrom(params));
+            out.println("app.runtime=" + getCfgRuntimeDir());
+            out.println("app.identifier=" + IDENTIFIER.fetchFrom(params));
+            out.println("app.classpath="
+                    + getCfgClassPath(CLASSPATH.fetchFrom(params)));
+
+            // The main app is required to be a jar, modular or unnamed.
+            if (mainModule != null &&
+                    (mainJarType == ModFile.ModType.Unknown ||
+                    mainJarType == ModFile.ModType.ModularJar)) {
+                out.println("app.mainmodule=" + mainModule);
+            } else {
+                String mainClass =
+                        StandardBundlerParam.MAIN_CLASS.fetchFrom(params);
+                // If the app is contained in an unnamed jar then launch it the
+                // legacy way and the main class string must be
+                // of the format com/foo/Main
+                if (mainJar != null) {
+                    out.println("app.mainjar=" + getCfgAppDir()
+                            + mainJar.toPath().getFileName().toString());
+                }
+                if (mainClass != null) {
+                    out.println("app.mainclass="
+                            + mainClass.replace("\\", "/"));
+                }
+            }
+
+            out.println();
+            out.println("[JavaOptions]");
+            List<String> jvmargs = JAVA_OPTIONS.fetchFrom(params);
+            for (String arg : jvmargs) {
+                out.println(arg);
+            }
+            Path modsDir = getAppModsDir();
+
+            if (modsDir != null && modsDir.toFile().exists()) {
+                out.println("--module-path");
+                out.println(getCfgAppDir().replace("\\","/") + "mods");
+            }
+
+            out.println();
+            out.println("[ArgOptions]");
+            List<String> args = ARGUMENTS.fetchFrom(params);
+            for (String arg : args) {
+                if (arg.endsWith("=") &&
+                        (arg.indexOf("=") == arg.lastIndexOf("="))) {
+                    out.print(arg.substring(0, arg.length() - 1));
+                    out.println("\\=");
+                } else {
+                    out.println(arg);
+                }
+            }
+        }
+    }
+
+    File getRuntimeImageDir(File runtimeImageTop) {
+        return runtimeImageTop;
+    }
+
+    protected String getCfgAppDir() {
+        return "$ROOTDIR" + File.separator
+                + getAppDir().getFileName() + File.separator;
+    }
+
+    protected String getCfgRuntimeDir() {
+        return "$ROOTDIR" + File.separator + "runtime";
+    }
+
+    String getCfgClassPath(String classpath) {
+        String cfgAppDir = getCfgAppDir();
+
+        StringBuilder sb = new StringBuilder();
+        for (String path : classpath.split("[:;]")) {
+            if (path.length() > 0) {
+                sb.append(cfgAppDir);
+                sb.append(path);
+                sb.append(File.pathSeparator);
+            }
+        }
+        if (sb.length() > 0) {
+            sb.deleteCharAt(sb.length() - 1);
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+
+/**
+ * AbstractBundler
+ *
+ * This is the base class all bundlers extend from.
+ * It contains methods and parameters common to all bundlers.
+ * The concrete implementations are in the platform specific bundlers.
+ */
+abstract class AbstractBundler implements Bundler {
+
+    static final BundlerParamInfo<File> IMAGES_ROOT =
+            new StandardBundlerParam<>(
+            "imagesRoot",
+            File.class,
+            params -> new File(
+                StandardBundlerParam.TEMP_ROOT.fetchFrom(params), "images"),
+            (s, p) -> null);
+
+    @Override
+    public String toString() {
+        return getName();
+    }
+
+    @Override
+    public void cleanup(Map<String, ? super Object> params) {
+        try {
+            IOUtils.deleteRecursive(
+                    StandardBundlerParam.TEMP_ROOT.fetchFrom(params));
+        } catch (IOException e) {
+            Log.verbose(e.getMessage());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractImageBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, 2019, 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.incubator.jpackage.internal;
+
+import java.text.MessageFormat;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.io.File;
+import java.io.IOException;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+/**
+ * AbstractImageBundler
+ *
+ * This is the base class for each of the Application Image Bundlers.
+ *
+ * It contains methods and parameters common to all Image Bundlers.
+ *
+ * Application Image Bundlers are created in "create-app-image" mode,
+ * or as an intermediate step in "create-installer" mode.
+ *
+ * The concrete implementations are in the platform specific Bundlers.
+ */
+public abstract class AbstractImageBundler extends AbstractBundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MainResources");
+
+    public void imageBundleValidation(Map<String, ? super Object> params)
+             throws ConfigException {
+        StandardBundlerParam.validateMainClassInfoFromAppResources(params);
+
+    }
+
+    protected File createRoot(Map<String, ? super Object> params,
+            File outputDirectory, boolean dependentTask, String name)
+            throws PackagerException {
+
+        IOUtils.writableOutputDir(outputDirectory.toPath());
+
+        if (!dependentTask) {
+            Log.verbose(MessageFormat.format(
+                    I18N.getString("message.creating-app-bundle"),
+                    name, outputDirectory.getAbsolutePath()));
+        }
+
+        // NAME will default to CLASS, so the real problem is no MAIN_CLASS
+        if (name == null) {
+            throw new PackagerException("ERR_NoMainClass");
+        }
+
+        // Create directory structure
+        File rootDirectory = new File(outputDirectory, name);
+
+        if (rootDirectory.exists()) {
+            throw new PackagerException("error.root-exists",
+                    rootDirectory.getAbsolutePath());
+        }
+
+        rootDirectory.mkdirs();
+
+        return rootDirectory;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AddLauncherArguments.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2018, 2019, 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.incubator.jpackage.internal;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.io.File;
+import jdk.incubator.jpackage.internal.Arguments.CLIOptions;
+
+/*
+ * AddLauncherArguments
+ *
+ * Processes a add-launcher properties file to create the Map of
+ * bundle params applicable to the add-launcher:
+ *
+ * BundlerParams p = (new AddLauncherArguments(file)).getLauncherMap();
+ *
+ * A add-launcher is another executable program generated by either the
+ * create-app-image mode or the create-installer mode.
+ * The add-launcher may be the same program with different configuration,
+ * or a completely different program created from the same files.
+ *
+ * There may be multiple add-launchers, each created by using the
+ * command line arg "--add-launcher <file path>
+ *
+ * The add-launcher properties file may have any of:
+ *
+ * appVersion
+ * module
+ * main-jar
+ * main-class
+ * icon
+ * arguments
+ * java-options
+ * win-console
+ * linux-app-category
+ *
+ */
+class AddLauncherArguments {
+
+    private final String name;
+    private final String filename;
+    private Map<String, String> allArgs;
+    private Map<String, ? super Object> bundleParams;
+
+    AddLauncherArguments(String name, String filename) {
+        this.name = name;
+        this.filename = filename;
+    }
+
+    private void initLauncherMap() {
+        if (bundleParams != null) {
+            return;
+        }
+
+        allArgs = Arguments.getPropertiesFromFile(filename);
+        allArgs.put(CLIOptions.NAME.getId(), name);
+
+        bundleParams = new HashMap<>();
+        String mainJar = getOptionValue(CLIOptions.MAIN_JAR);
+        String mainClass = getOptionValue(CLIOptions.APPCLASS);
+        String module = getOptionValue(CLIOptions.MODULE);
+
+        if (module != null && mainClass != null) {
+            putUnlessNull(bundleParams, CLIOptions.MODULE.getId(),
+                    module + "/" + mainClass);
+        } else if (module != null) {
+            putUnlessNull(bundleParams, CLIOptions.MODULE.getId(),
+                    module);
+        } else {
+            putUnlessNull(bundleParams, CLIOptions.MAIN_JAR.getId(),
+                    mainJar);
+            putUnlessNull(bundleParams, CLIOptions.APPCLASS.getId(),
+                    mainClass);
+        }
+
+        putUnlessNull(bundleParams, CLIOptions.NAME.getId(),
+                getOptionValue(CLIOptions.NAME));
+
+        putUnlessNull(bundleParams, CLIOptions.VERSION.getId(),
+                getOptionValue(CLIOptions.VERSION));
+
+        putUnlessNull(bundleParams, CLIOptions.RELEASE.getId(),
+                getOptionValue(CLIOptions.RELEASE));
+
+        putUnlessNull(bundleParams, CLIOptions.LINUX_CATEGORY.getId(),
+                getOptionValue(CLIOptions.LINUX_CATEGORY));
+
+        putUnlessNull(bundleParams,
+                CLIOptions.WIN_CONSOLE_HINT.getId(),
+                getOptionValue(CLIOptions.WIN_CONSOLE_HINT));
+
+        String value = getOptionValue(CLIOptions.ICON);
+        putUnlessNull(bundleParams, CLIOptions.ICON.getId(),
+                (value == null) ? null : new File(value));
+
+        // "arguments" and "java-options" even if value is null:
+        if (allArgs.containsKey(CLIOptions.ARGUMENTS.getId())) {
+            String argumentStr = getOptionValue(CLIOptions.ARGUMENTS);
+            bundleParams.put(CLIOptions.ARGUMENTS.getId(),
+                    Arguments.getArgumentList(argumentStr));
+        }
+
+        if (allArgs.containsKey(CLIOptions.JAVA_OPTIONS.getId())) {
+            String jvmargsStr = getOptionValue(CLIOptions.JAVA_OPTIONS);
+            bundleParams.put(CLIOptions.JAVA_OPTIONS.getId(),
+                    Arguments.getArgumentList(jvmargsStr));
+        }
+    }
+
+    private String getOptionValue(CLIOptions option) {
+        if (option == null || allArgs == null) {
+            return null;
+        }
+
+        String id = option.getId();
+
+        if (allArgs.containsKey(id)) {
+            return allArgs.get(id);
+        }
+
+        return null;
+    }
+
+    Map<String, ? super Object> getLauncherMap() {
+        initLauncherMap();
+        return bundleParams;
+    }
+
+    private void putUnlessNull(Map<String, ? super Object> params,
+            String param, Object value) {
+        if (value != null) {
+            params.put(param, value);
+        }
+    }
+
+    static Map<String, ? super Object> merge(
+            Map<String, ? super Object> original,
+            Map<String, ? super Object> additional) {
+        Map<String, ? super Object> tmp = new HashMap<>(original);
+        if (additional.containsKey(CLIOptions.MODULE.getId())) {
+            tmp.remove(CLIOptions.MAIN_JAR.getId());
+            tmp.remove(CLIOptions.APPCLASS.getId());
+        } else if (additional.containsKey(CLIOptions.MAIN_JAR.getId())) {
+            tmp.remove(CLIOptions.MODULE.getId());
+        }
+        if (additional.containsKey(CLIOptions.ARGUMENTS.getId())) {
+            // if add launcher properties file contains "arguments", even with
+            // null value, disregard the "arguments" from command line
+            tmp.remove(CLIOptions.ARGUMENTS.getId());
+        }
+        if (additional.containsKey(CLIOptions.JAVA_OPTIONS.getId())) {
+            // same thing for java-options
+            tmp.remove(CLIOptions.JAVA_OPTIONS.getId());
+        }
+        tmp.putAll(additional);
+        return tmp;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageFile.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+public class AppImageFile {
+
+    // These values will be loaded from AppImage xml file.
+    private final String creatorVersion;
+    private final String creatorPlatform;
+    private final String launcherName;
+    private final List<String> addLauncherNames;
+
+    private final static String FILENAME = ".jpackage.xml";
+
+    private final static Map<Platform, String> PLATFORM_LABELS = Map.of(
+            Platform.LINUX, "linux", Platform.WINDOWS, "windows", Platform.MAC,
+            "macOS");
+
+
+    private AppImageFile() {
+        this(null, null, null, null);
+    }
+
+    private AppImageFile(String launcherName, List<String> addLauncherNames,
+            String creatorVersion, String creatorPlatform) {
+        this.launcherName = launcherName;
+        this.addLauncherNames = addLauncherNames;
+        this.creatorVersion = creatorVersion;
+        this.creatorPlatform = creatorPlatform;
+    }
+
+    /**
+     * Returns list of additional launchers configured for the application.
+     * Each item in the list is not null or empty string.
+     * Returns empty list for application without additional launchers.
+     */
+    List<String> getAddLauncherNames() {
+        return addLauncherNames;
+    }
+
+    /**
+     * Returns main application launcher name. Never returns null or empty value.
+     */
+    String getLauncherName() {
+        return launcherName;
+    }
+
+    void verifyCompatible() throws ConfigException {
+        // Just do nothing for now.
+    }
+
+    /**
+     * Returns path to application image info file.
+     * @param appImageDir - path to application image
+     */
+    public static Path getPathInAppImage(Path appImageDir) {
+        return appImageDir.resolve(FILENAME);
+    }
+
+    /**
+     * Saves file with application image info in application image.
+     * @param appImageDir - path to application image
+     * @throws IOException
+     */
+    static void save(Path appImageDir, Map<String, Object> params)
+            throws IOException {
+        IOUtils.createXml(getPathInAppImage(appImageDir), xml -> {
+            xml.writeStartElement("jpackage-state");
+            xml.writeAttribute("version", getVersion());
+            xml.writeAttribute("platform", getPlatform());
+
+            xml.writeStartElement("main-launcher");
+            xml.writeCharacters(APP_NAME.fetchFrom(params));
+            xml.writeEndElement();
+
+            List<Map<String, ? super Object>> addLaunchers =
+                ADD_LAUNCHERS.fetchFrom(params);
+
+            for (int i = 0; i < addLaunchers.size(); i++) {
+                Map<String, ? super Object> sl = addLaunchers.get(i);
+                xml.writeStartElement("add-launcher");
+                xml.writeCharacters(APP_NAME.fetchFrom(sl));
+                xml.writeEndElement();
+            }
+        });
+    }
+
+    /**
+     * Loads application image info from application image.
+     * @param appImageDir - path to application image
+     * @return valid info about application image or null
+     * @throws IOException
+     */
+    static AppImageFile load(Path appImageDir) throws IOException {
+        try {
+            Path path = getPathInAppImage(appImageDir);
+            DocumentBuilderFactory dbf =
+                    DocumentBuilderFactory.newDefaultInstance();
+            dbf.setFeature(
+                   "http://apache.org/xml/features/nonvalidating/load-external-dtd",
+                    false);
+            DocumentBuilder b = dbf.newDocumentBuilder();
+            Document doc = b.parse(new FileInputStream(path.toFile()));
+
+            XPath xPath = XPathFactory.newInstance().newXPath();
+
+            String mainLauncher = xpathQueryNullable(xPath,
+                    "/jpackage-state/main-launcher/text()", doc);
+            if (mainLauncher == null) {
+                // No main launcher, this is fatal.
+                return new AppImageFile();
+            }
+
+            List<String> addLaunchers = new ArrayList<String>();
+
+            String platform = xpathQueryNullable(xPath,
+                    "/jpackage-state/@platform", doc);
+
+            String version = xpathQueryNullable(xPath,
+                    "/jpackage-state/@version", doc);
+
+            NodeList launcherNameNodes = (NodeList) xPath.evaluate(
+                    "/jpackage-state/add-launcher/text()", doc,
+                    XPathConstants.NODESET);
+
+            for (int i = 0; i != launcherNameNodes.getLength(); i++) {
+                addLaunchers.add(launcherNameNodes.item(i).getNodeValue());
+            }
+
+            AppImageFile file = new AppImageFile(
+                    mainLauncher, addLaunchers, version, platform);
+            if (!file.isValid()) {
+                file = new AppImageFile();
+            }
+            return file;
+        } catch (ParserConfigurationException | SAXException ex) {
+            // Let caller sort this out
+            throw new IOException(ex);
+        } catch (XPathExpressionException ex) {
+            // This should never happen as XPath expressions should be correct
+            throw new RuntimeException(ex);
+        }
+    }
+
+    /**
+     * Returns list of launcher names configured for the application.
+     * The first item in the returned list is main launcher name.
+     * Following items in the list are names of additional launchers.
+     */
+    static List<String> getLauncherNames(Path appImageDir,
+            Map<String, ? super Object> params) {
+        List<String> launchers = new ArrayList<>();
+        try {
+            AppImageFile appImageInfo = AppImageFile.load(appImageDir);
+            if (appImageInfo != null) {
+                launchers.add(appImageInfo.getLauncherName());
+                launchers.addAll(appImageInfo.getAddLauncherNames());
+                return launchers;
+            }
+        } catch (IOException ioe) {
+            Log.verbose(ioe);
+        }
+
+        launchers.add(APP_NAME.fetchFrom(params));
+        ADD_LAUNCHERS.fetchFrom(params).stream().map(APP_NAME::fetchFrom).forEach(
+                launchers::add);
+        return launchers;
+    }
+
+    private static String xpathQueryNullable(XPath xPath, String xpathExpr,
+            Document xml) throws XPathExpressionException {
+        NodeList nodes = (NodeList) xPath.evaluate(xpathExpr, xml,
+                XPathConstants.NODESET);
+        if (nodes != null && nodes.getLength() > 0) {
+            return nodes.item(0).getNodeValue();
+        }
+        return null;
+    }
+
+    private static String getVersion() {
+        return System.getProperty("java.version");
+    }
+
+    private static String getPlatform() {
+        return PLATFORM_LABELS.get(Platform.getPlatform());
+    }
+
+    private boolean isValid() {
+        if (launcherName == null || launcherName.length() == 0 ||
+            addLauncherNames.indexOf("") != -1) {
+            // Some launchers have empty names. This is invalid.
+            return false;
+        }
+
+        // Add more validation.
+
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ApplicationLayout.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.nio.file.Path;
+import java.util.Map;
+
+
+/**
+ * Application directory layout.
+ */
+public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayout> {
+    enum PathRole {
+        RUNTIME, APP, LAUNCHERS, DESKTOP, APP_MODS, DLLS
+    }
+
+    ApplicationLayout(Map<Object, Path> paths) {
+        data = new PathGroup(paths);
+    }
+
+    private ApplicationLayout(PathGroup data) {
+        this.data = data;
+    }
+
+    @Override
+    public PathGroup pathGroup() {
+        return data;
+    }
+
+    @Override
+    public ApplicationLayout resolveAt(Path root) {
+        return new ApplicationLayout(pathGroup().resolveAt(root));
+    }
+
+    /**
+     * Path to launchers directory.
+     */
+    public Path launchersDirectory() {
+        return pathGroup().getPath(PathRole.LAUNCHERS);
+    }
+
+    /**
+     * Path to directory with dynamic libraries.
+     */
+    public Path dllDirectory() {
+        return pathGroup().getPath(PathRole.DLLS);
+    }
+
+    /**
+     * Path to application data directory.
+     */
+    public Path appDirectory() {
+        return pathGroup().getPath(PathRole.APP);
+    }
+
+    /**
+     * Path to Java runtime directory.
+     */
+    public Path runtimeDirectory() {
+        return pathGroup().getPath(PathRole.RUNTIME);
+    }
+
+    /**
+     * Path to application mods directory.
+     */
+    public Path appModsDirectory() {
+        return pathGroup().getPath(PathRole.APP_MODS);
+    }
+
+    /**
+     * Path to directory with application's desktop integration files.
+     */
+    public Path destktopIntegrationDirectory() {
+        return pathGroup().getPath(PathRole.DESKTOP);
+    }
+
+    static ApplicationLayout linuxAppImage() {
+        return new ApplicationLayout(Map.of(
+                PathRole.LAUNCHERS, Path.of("bin"),
+                PathRole.APP, Path.of("lib/app"),
+                PathRole.RUNTIME, Path.of("lib/runtime"),
+                PathRole.DESKTOP, Path.of("lib"),
+                PathRole.DLLS, Path.of("lib"),
+                PathRole.APP_MODS, Path.of("lib/app/mods")
+        ));
+    }
+
+    static ApplicationLayout windowsAppImage() {
+        return new ApplicationLayout(Map.of(
+                PathRole.LAUNCHERS, Path.of(""),
+                PathRole.APP, Path.of("app"),
+                PathRole.RUNTIME, Path.of("runtime"),
+                PathRole.DESKTOP, Path.of(""),
+                PathRole.DLLS, Path.of(""),
+                PathRole.APP_MODS, Path.of("app/mods")
+        ));
+    }
+
+    static ApplicationLayout macAppImage() {
+        return new ApplicationLayout(Map.of(
+                PathRole.LAUNCHERS, Path.of("Contents/MacOS"),
+                PathRole.APP, Path.of("Contents/app"),
+                PathRole.RUNTIME, Path.of("Contents/runtime"),
+                PathRole.DESKTOP, Path.of("Contents/Resources"),
+                PathRole.DLLS, Path.of("Contents/MacOS"),
+                PathRole.APP_MODS, Path.of("Contents/app/mods")
+        ));
+    }
+
+    public static ApplicationLayout platformAppImage() {
+        if (Platform.isWindows()) {
+            return windowsAppImage();
+        }
+
+        if (Platform.isLinux()) {
+            return linuxAppImage();
+        }
+
+        if (Platform.isMac()) {
+            return macAppImage();
+        }
+
+        throw Platform.throwUnknownPlatformError();
+    }
+
+    public static ApplicationLayout javaRuntime() {
+        return new ApplicationLayout(Map.of(PathRole.RUNTIME, Path.of("")));
+    }
+
+    private final PathGroup data;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ArgAction.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 2019, 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.incubator.jpackage.internal;
+
+@FunctionalInterface
+interface ArgAction {
+    void execute();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Arguments.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,802 @@
+/*
+ * Copyright (c) 2018, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.stream.Stream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Arguments
+ *
+ * This class encapsulates and processes the command line arguments,
+ * in effect, implementing all the work of jpackage tool.
+ *
+ * The primary entry point, processArguments():
+ * Processes and validates command line arguments, constructing DeployParams.
+ * Validates the DeployParams, and generate the BundleParams.
+ * Generates List of Bundlers from BundleParams valid for this platform.
+ * Executes each Bundler in the list.
+ */
+public class Arguments {
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MainResources");
+
+    private static final String FA_EXTENSIONS = "extension";
+    private static final String FA_CONTENT_TYPE = "mime-type";
+    private static final String FA_DESCRIPTION = "description";
+    private static final String FA_ICON = "icon";
+
+    // regexp for parsing args (for example, for additional launchers)
+    private static Pattern pattern = Pattern.compile(
+          "(?:(?:([\"'])(?:\\\\\\1|.)*?(?:\\1|$))|(?:\\\\[\"'\\s]|[^\\s]))++");
+
+    private DeployParams deployParams = null;
+
+    private int pos = 0;
+    private List<String> argList = null;
+
+    private List<CLIOptions> allOptions = null;
+
+    private String input = null;
+    private String output = null;
+
+    private boolean hasMainJar = false;
+    private boolean hasMainClass = false;
+    private boolean hasMainModule = false;
+    public boolean userProvidedBuildRoot = false;
+
+    private String buildRoot = null;
+    private String mainJarPath = null;
+
+    private static boolean runtimeInstaller = false;
+
+    private List<AddLauncherArguments> addLaunchers = null;
+
+    private static Map<String, CLIOptions> argIds = new HashMap<>();
+    private static Map<String, CLIOptions> argShortIds = new HashMap<>();
+
+    static {
+        // init maps for parsing arguments
+        (EnumSet.allOf(CLIOptions.class)).forEach(option -> {
+            argIds.put(option.getIdWithPrefix(), option);
+            if (option.getShortIdWithPrefix() != null) {
+                argShortIds.put(option.getShortIdWithPrefix(), option);
+            }
+        });
+    }
+
+    public Arguments(String[] args) {
+        argList = new ArrayList<String>(args.length);
+        for (String arg : args) {
+            argList.add(arg);
+        }
+        Log.verbose ("\njpackage argument list: \n" + argList + "\n");
+        pos = 0;
+
+        deployParams = new DeployParams();
+
+        allOptions = new ArrayList<>();
+
+        addLaunchers = new ArrayList<>();
+
+        output = Paths.get("").toAbsolutePath().toString();
+        deployParams.setOutput(new File(output));
+    }
+
+    // CLIOptions is public for DeployParamsTest
+    public enum CLIOptions {
+        PACKAGE_TYPE("type", "t", OptionCategories.PROPERTY, () -> {
+            context().deployParams.setTargetFormat(popArg());
+        }),
+
+        INPUT ("input", "i", OptionCategories.PROPERTY, () -> {
+            context().input = popArg();
+            setOptionValue("input", context().input);
+        }),
+
+        OUTPUT ("dest", "d", OptionCategories.PROPERTY, () -> {
+            context().output = popArg();
+            context().deployParams.setOutput(new File(context().output));
+        }),
+
+        DESCRIPTION ("description", OptionCategories.PROPERTY),
+
+        VENDOR ("vendor", OptionCategories.PROPERTY),
+
+        APPCLASS ("main-class", OptionCategories.PROPERTY, () -> {
+            context().hasMainClass = true;
+            setOptionValue("main-class", popArg());
+        }),
+
+        NAME ("name", "n", OptionCategories.PROPERTY),
+
+        VERBOSE ("verbose", OptionCategories.PROPERTY, () -> {
+            setOptionValue("verbose", true);
+            Log.setVerbose();
+        }),
+
+        RESOURCE_DIR("resource-dir",
+                OptionCategories.PROPERTY, () -> {
+            String resourceDir = popArg();
+            setOptionValue("resource-dir", resourceDir);
+        }),
+
+        ARGUMENTS ("arguments", OptionCategories.PROPERTY, () -> {
+            List<String> arguments = getArgumentList(popArg());
+            setOptionValue("arguments", arguments);
+        }),
+
+        ICON ("icon", OptionCategories.PROPERTY),
+
+        COPYRIGHT ("copyright", OptionCategories.PROPERTY),
+
+        LICENSE_FILE ("license-file", OptionCategories.PROPERTY),
+
+        VERSION ("app-version", OptionCategories.PROPERTY),
+
+        RELEASE ("linux-app-release", OptionCategories.PROPERTY),
+
+        JAVA_OPTIONS ("java-options", OptionCategories.PROPERTY, () -> {
+            List<String> args = getArgumentList(popArg());
+            args.forEach(a -> setOptionValue("java-options", a));
+        }),
+
+        FILE_ASSOCIATIONS ("file-associations",
+                OptionCategories.PROPERTY, () -> {
+            Map<String, ? super Object> args = new HashMap<>();
+
+            // load .properties file
+            Map<String, String> initialMap = getPropertiesFromFile(popArg());
+
+            String ext = initialMap.get(FA_EXTENSIONS);
+            if (ext != null) {
+                args.put(StandardBundlerParam.FA_EXTENSIONS.getID(), ext);
+            }
+
+            String type = initialMap.get(FA_CONTENT_TYPE);
+            if (type != null) {
+                args.put(StandardBundlerParam.FA_CONTENT_TYPE.getID(), type);
+            }
+
+            String desc = initialMap.get(FA_DESCRIPTION);
+            if (desc != null) {
+                args.put(StandardBundlerParam.FA_DESCRIPTION.getID(), desc);
+            }
+
+            String icon = initialMap.get(FA_ICON);
+            if (icon != null) {
+                args.put(StandardBundlerParam.FA_ICON.getID(), icon);
+            }
+
+            ArrayList<Map<String, ? super Object>> associationList =
+                new ArrayList<Map<String, ? super Object>>();
+
+            associationList.add(args);
+
+            // check that we really add _another_ value to the list
+            setOptionValue("file-associations", associationList);
+
+        }),
+
+        ADD_LAUNCHER ("add-launcher",
+                    OptionCategories.PROPERTY, () -> {
+            String spec = popArg();
+            String name = null;
+            String filename = spec;
+            if (spec.contains("=")) {
+                String[] values = spec.split("=", 2);
+                name = values[0];
+                filename = values[1];
+            }
+            context().addLaunchers.add(
+                new AddLauncherArguments(name, filename));
+        }),
+
+        TEMP_ROOT ("temp", OptionCategories.PROPERTY, () -> {
+            context().buildRoot = popArg();
+            context().userProvidedBuildRoot = true;
+            setOptionValue("temp", context().buildRoot);
+        }),
+
+        INSTALL_DIR ("install-dir", OptionCategories.PROPERTY),
+
+        PREDEFINED_APP_IMAGE ("app-image", OptionCategories.PROPERTY),
+
+        PREDEFINED_RUNTIME_IMAGE ("runtime-image", OptionCategories.PROPERTY),
+
+        MAIN_JAR ("main-jar",  OptionCategories.PROPERTY, () -> {
+            context().mainJarPath = popArg();
+            context().hasMainJar = true;
+            setOptionValue("main-jar", context().mainJarPath);
+        }),
+
+        MODULE ("module", "m", OptionCategories.MODULAR, () -> {
+            context().hasMainModule = true;
+            setOptionValue("module", popArg());
+        }),
+
+        ADD_MODULES ("add-modules", OptionCategories.MODULAR),
+
+        MODULE_PATH ("module-path", "p", OptionCategories.MODULAR),
+
+        BIND_SERVICES ("bind-services", OptionCategories.PROPERTY, () -> {
+            setOptionValue("bind-services", true);
+        }),
+
+        MAC_SIGN ("mac-sign", "s", OptionCategories.PLATFORM_MAC, () -> {
+            setOptionValue("mac-sign", true);
+        }),
+
+        MAC_BUNDLE_NAME ("mac-package-name", OptionCategories.PLATFORM_MAC),
+
+        MAC_BUNDLE_IDENTIFIER("mac-package-identifier",
+                    OptionCategories.PLATFORM_MAC),
+
+        MAC_BUNDLE_SIGNING_PREFIX ("mac-package-signing-prefix",
+                    OptionCategories.PLATFORM_MAC),
+
+        MAC_SIGNING_KEY_NAME ("mac-signing-key-user-name",
+                    OptionCategories.PLATFORM_MAC),
+
+        MAC_SIGNING_KEYCHAIN ("mac-signing-keychain",
+                    OptionCategories.PLATFORM_MAC),
+
+        MAC_APP_STORE_ENTITLEMENTS ("mac-app-store-entitlements",
+                    OptionCategories.PLATFORM_MAC),
+
+        WIN_MENU_HINT ("win-menu", OptionCategories.PLATFORM_WIN, () -> {
+            setOptionValue("win-menu", true);
+        }),
+
+        WIN_MENU_GROUP ("win-menu-group", OptionCategories.PLATFORM_WIN),
+
+        WIN_SHORTCUT_HINT ("win-shortcut",
+                OptionCategories.PLATFORM_WIN, () -> {
+            setOptionValue("win-shortcut", true);
+        }),
+
+        WIN_PER_USER_INSTALLATION ("win-per-user-install",
+                OptionCategories.PLATFORM_WIN, () -> {
+            setOptionValue("win-per-user-install", false);
+        }),
+
+        WIN_DIR_CHOOSER ("win-dir-chooser",
+                OptionCategories.PLATFORM_WIN, () -> {
+            setOptionValue("win-dir-chooser", true);
+        }),
+
+        WIN_UPGRADE_UUID ("win-upgrade-uuid",
+                OptionCategories.PLATFORM_WIN),
+
+        WIN_CONSOLE_HINT ("win-console", OptionCategories.PLATFORM_WIN, () -> {
+            setOptionValue("win-console", true);
+        }),
+
+        LINUX_BUNDLE_NAME ("linux-package-name",
+                OptionCategories.PLATFORM_LINUX),
+
+        LINUX_DEB_MAINTAINER ("linux-deb-maintainer",
+                OptionCategories.PLATFORM_LINUX),
+
+        LINUX_CATEGORY ("linux-app-category",
+                OptionCategories.PLATFORM_LINUX),
+
+        LINUX_RPM_LICENSE_TYPE ("linux-rpm-license-type",
+                OptionCategories.PLATFORM_LINUX),
+
+        LINUX_PACKAGE_DEPENDENCIES ("linux-package-deps",
+                OptionCategories.PLATFORM_LINUX),
+
+        LINUX_SHORTCUT_HINT ("linux-shortcut",
+                OptionCategories.PLATFORM_LINUX, () -> {
+            setOptionValue("linux-shortcut", true);
+        }),
+
+        LINUX_MENU_GROUP ("linux-menu-group", OptionCategories.PLATFORM_LINUX);
+
+        private final String id;
+        private final String shortId;
+        private final OptionCategories category;
+        private final ArgAction action;
+        private static Arguments argContext;
+
+        private CLIOptions(String id, OptionCategories category) {
+            this(id, null, category, null);
+        }
+
+        private CLIOptions(String id, String shortId,
+                           OptionCategories category) {
+            this(id, shortId, category, null);
+        }
+
+        private CLIOptions(String id,
+                OptionCategories category, ArgAction action) {
+            this(id, null, category, action);
+        }
+
+        private CLIOptions(String id, String shortId,
+                           OptionCategories category, ArgAction action) {
+            this.id = id;
+            this.shortId = shortId;
+            this.action = action;
+            this.category = category;
+        }
+
+        static void setContext(Arguments context) {
+            argContext = context;
+        }
+
+        public static Arguments context() {
+            if (argContext != null) {
+                return argContext;
+            } else {
+                throw new RuntimeException("Argument context is not set.");
+            }
+        }
+
+        public String getId() {
+            return this.id;
+        }
+
+        String getIdWithPrefix() {
+            return "--" + this.id;
+        }
+
+        String getShortIdWithPrefix() {
+            return this.shortId == null ? null : "-" + this.shortId;
+        }
+
+        void execute() {
+            if (action != null) {
+                action.execute();
+            } else {
+                defaultAction();
+            }
+        }
+
+        private void defaultAction() {
+            context().deployParams.addBundleArgument(id, popArg());
+        }
+
+        private static void setOptionValue(String option, Object value) {
+            context().deployParams.addBundleArgument(option, value);
+        }
+
+        private static String popArg() {
+            nextArg();
+            return (context().pos >= context().argList.size()) ?
+                            "" : context().argList.get(context().pos);
+        }
+
+        private static String getArg() {
+            return (context().pos >= context().argList.size()) ?
+                        "" : context().argList.get(context().pos);
+        }
+
+        private static void nextArg() {
+            context().pos++;
+        }
+
+        private static boolean hasNextArg() {
+            return context().pos < context().argList.size();
+        }
+    }
+
+    enum OptionCategories {
+        MODULAR,
+        PROPERTY,
+        PLATFORM_MAC,
+        PLATFORM_WIN,
+        PLATFORM_LINUX;
+    }
+
+    public boolean processArguments() {
+        try {
+
+            // init context of arguments
+            CLIOptions.setContext(this);
+
+            // parse cmd line
+            String arg;
+            CLIOptions option;
+            for (; CLIOptions.hasNextArg(); CLIOptions.nextArg()) {
+                arg = CLIOptions.getArg();
+                if ((option = toCLIOption(arg)) != null) {
+                    // found a CLI option
+                    allOptions.add(option);
+                    option.execute();
+                } else {
+                    throw new PackagerException("ERR_InvalidOption", arg);
+                }
+            }
+
+            if (hasMainJar && !hasMainClass) {
+                // try to get main-class from manifest
+                String mainClass = getMainClassFromManifest();
+                if (mainClass != null) {
+                    CLIOptions.setOptionValue(
+                            CLIOptions.APPCLASS.getId(), mainClass);
+                }
+            }
+
+            // display error for arguments that are not supported
+            // for current configuration.
+
+            validateArguments();
+
+            addResources(deployParams, input, mainJarPath);
+
+            List<Map<String, ? super Object>> launchersAsMap =
+                    new ArrayList<>();
+
+            for (AddLauncherArguments sl : addLaunchers) {
+                launchersAsMap.add(sl.getLauncherMap());
+            }
+
+            deployParams.addBundleArgument(
+                    StandardBundlerParam.ADD_LAUNCHERS.getID(),
+                    launchersAsMap);
+
+            // at this point deployParams should be already configured
+
+            deployParams.validate();
+
+            BundleParams bp = deployParams.getBundleParams();
+
+            // validate name(s)
+            ArrayList<String> usedNames = new ArrayList<String>();
+            usedNames.add(bp.getName()); // add main app name
+
+            for (AddLauncherArguments sl : addLaunchers) {
+                Map<String, ? super Object> slMap = sl.getLauncherMap();
+                String slName =
+                        (String) slMap.get(Arguments.CLIOptions.NAME.getId());
+                if (slName == null) {
+                    throw new PackagerException("ERR_NoAddLauncherName");
+                }
+                // same rules apply to additional launcher names as app name
+                DeployParams.validateName(slName, false);
+                for (String usedName : usedNames) {
+                    if (slName.equals(usedName)) {
+                        throw new PackagerException("ERR_NoUniqueName");
+                    }
+                }
+                usedNames.add(slName);
+            }
+            if (runtimeInstaller && bp.getName() == null) {
+                throw new PackagerException("ERR_NoJreInstallerName");
+            }
+
+            generateBundle(bp.getBundleParamsAsMap());
+            return true;
+        } catch (Exception e) {
+            if (Log.isVerbose()) {
+                Log.verbose(e);
+            } else {
+                String msg1 = e.getMessage();
+                Log.error(msg1);
+                if (e.getCause() != null && e.getCause() != e) {
+                    String msg2 = e.getCause().getMessage();
+                    if (msg2 != null && !msg1.contains(msg2)) {
+                        Log.error(msg2);
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
+    private void validateArguments() throws PackagerException {
+        String type = deployParams.getTargetFormat();
+        String ptype = (type != null) ? type : "default";
+        boolean imageOnly = deployParams.isTargetAppImage();
+        boolean hasAppImage = allOptions.contains(
+                CLIOptions.PREDEFINED_APP_IMAGE);
+        boolean hasRuntime = allOptions.contains(
+                CLIOptions.PREDEFINED_RUNTIME_IMAGE);
+        boolean installerOnly = !imageOnly && hasAppImage;
+        runtimeInstaller = !imageOnly && hasRuntime && !hasAppImage &&
+                !hasMainModule && !hasMainJar;
+
+        for (CLIOptions option : allOptions) {
+            if (!ValidOptions.checkIfSupported(option)) {
+                // includes option valid only on different platform
+                throw new PackagerException("ERR_UnsupportedOption",
+                        option.getIdWithPrefix());
+            }
+            if (imageOnly) {
+                if (!ValidOptions.checkIfImageSupported(option)) {
+                    throw new PackagerException("ERR_InvalidTypeOption",
+                        option.getIdWithPrefix(), type);
+                }
+            } else if (installerOnly || runtimeInstaller) {
+                if (!ValidOptions.checkIfInstallerSupported(option)) {
+                    if (runtimeInstaller) {
+                        throw new PackagerException("ERR_NoInstallerEntryPoint",
+                            option.getIdWithPrefix());
+                    } else {
+                        throw new PackagerException("ERR_InvalidTypeOption",
+                            option.getIdWithPrefix(), ptype);
+                   }
+                }
+            }
+        }
+        if (installerOnly && hasRuntime) {
+            // note --runtime-image is only for image or runtime installer.
+            throw new PackagerException("ERR_InvalidTypeOption",
+                    CLIOptions.PREDEFINED_RUNTIME_IMAGE.getIdWithPrefix(),
+                    ptype);
+        }
+        if (hasMainJar && hasMainModule) {
+            throw new PackagerException("ERR_BothMainJarAndModule");
+        }
+        if (imageOnly && !hasMainJar && !hasMainModule) {
+            throw new PackagerException("ERR_NoEntryPoint");
+        }
+    }
+
+    private jdk.incubator.jpackage.internal.Bundler getPlatformBundler() {
+        boolean appImage = deployParams.isTargetAppImage();
+        String type = deployParams.getTargetFormat();
+        String bundleType = (appImage ?  "IMAGE" : "INSTALLER");
+
+        for (jdk.incubator.jpackage.internal.Bundler bundler :
+                Bundlers.createBundlersInstance().getBundlers(bundleType)) {
+            if (type == null) {
+                 if (bundler.isDefault()
+                         && bundler.supported(runtimeInstaller)) {
+                     return bundler;
+                 }
+            } else {
+                 if ((appImage || type.equalsIgnoreCase(bundler.getID()))
+                         && bundler.supported(runtimeInstaller)) {
+                     return bundler;
+                 }
+            }
+        }
+        return null;
+    }
+
+    private void generateBundle(Map<String,? super Object> params)
+            throws PackagerException {
+
+        boolean bundleCreated = false;
+
+        // the temp dir needs to be fetched from the params early,
+        // to prevent each copy of the params (such as may be used for
+        // additional launchers) from generating a separate temp dir when
+        // the default is used (the default is a new temp directory)
+        // The bundler.cleanup() below would not otherwise be able to
+        // clean these extra (and unneeded) temp directories.
+        StandardBundlerParam.TEMP_ROOT.fetchFrom(params);
+
+        // determine what bundler to run
+        jdk.incubator.jpackage.internal.Bundler bundler = getPlatformBundler();
+
+        if (bundler == null) {
+            throw new PackagerException("ERR_InvalidInstallerType",
+                      deployParams.getTargetFormat());
+        }
+
+        Map<String, ? super Object> localParams = new HashMap<>(params);
+        try {
+            bundler.validate(localParams);
+            File result = bundler.execute(localParams, deployParams.outdir);
+            if (result == null) {
+                throw new PackagerException("MSG_BundlerFailed",
+                        bundler.getID(), bundler.getName());
+            }
+            Log.verbose(MessageFormat.format(
+                    I18N.getString("message.bundle-created"),
+                    bundler.getName()));
+        } catch (ConfigException e) {
+            Log.verbose(e);
+            if (e.getAdvice() != null)  {
+                throw new PackagerException(e, "MSG_BundlerConfigException",
+                        bundler.getName(), e.getMessage(), e.getAdvice());
+            } else {
+                throw new PackagerException(e,
+                       "MSG_BundlerConfigExceptionNoAdvice",
+                        bundler.getName(), e.getMessage());
+            }
+        } catch (RuntimeException re) {
+            Log.verbose(re);
+            throw new PackagerException(re, "MSG_BundlerRuntimeException",
+                    bundler.getName(), re.toString());
+        } finally {
+            if (userProvidedBuildRoot) {
+                Log.verbose(MessageFormat.format(
+                        I18N.getString("message.debug-working-directory"),
+                        (new File(buildRoot)).getAbsolutePath()));
+            } else {
+                // always clean up the temporary directory created
+                // when --temp option not used.
+                bundler.cleanup(localParams);
+            }
+        }
+    }
+
+    private void addResources(DeployParams deployParams,
+            String inputdir, String mainJar) throws PackagerException {
+
+        if (inputdir == null || inputdir.isEmpty()) {
+            return;
+        }
+
+        File baseDir = new File(inputdir);
+
+        if (!baseDir.isDirectory()) {
+            throw new PackagerException("ERR_InputNotDirectory", inputdir);
+        }
+        if (!baseDir.canRead()) {
+            throw new PackagerException("ERR_CannotReadInputDir", inputdir);
+        }
+
+        List<String> fileNames;
+        fileNames = new ArrayList<>();
+        try (Stream<Path> files = Files.list(baseDir.toPath())) {
+            files.forEach(file -> fileNames.add(
+                    file.getFileName().toString()));
+        } catch (IOException e) {
+            Log.error("Unable to add resources: " + e.getMessage());
+        }
+        fileNames.forEach(file -> deployParams.addResource(baseDir, file));
+
+        deployParams.setClasspath(mainJar);
+    }
+
+    static CLIOptions toCLIOption(String arg) {
+        CLIOptions option;
+        if ((option = argIds.get(arg)) == null) {
+            option = argShortIds.get(arg);
+        }
+        return option;
+    }
+
+    static Map<String, String> getPropertiesFromFile(String filename) {
+        Map<String, String> map = new HashMap<>();
+        // load properties file
+        File file = new File(filename);
+        Properties properties = new Properties();
+        try (FileInputStream in = new FileInputStream(file)) {
+            properties.load(in);
+        } catch (IOException e) {
+            Log.error("Exception: " + e.getMessage());
+        }
+
+        for (final String name: properties.stringPropertyNames()) {
+            map.put(name, properties.getProperty(name));
+        }
+
+        return map;
+    }
+
+    static List<String> getArgumentList(String inputString) {
+        List<String> list = new ArrayList<>();
+        if (inputString == null || inputString.isEmpty()) {
+             return list;
+        }
+
+        // The "pattern" regexp attempts to abide to the rule that
+        // strings are delimited by whitespace unless surrounded by
+        // quotes, then it is anything (including spaces) in the quotes.
+        Matcher m = pattern.matcher(inputString);
+        while (m.find()) {
+            String s = inputString.substring(m.start(), m.end()).trim();
+            // Ensure we do not have an empty string. trim() will take care of
+            // whitespace only strings. The regex preserves quotes and escaped
+            // chars so we need to clean them before adding to the List
+            if (!s.isEmpty()) {
+                list.add(unquoteIfNeeded(s));
+            }
+        }
+        return list;
+    }
+
+    private static String unquoteIfNeeded(String in) {
+        if (in == null) {
+            return null;
+        }
+
+        if (in.isEmpty()) {
+            return "";
+        }
+
+        // Use code points to preserve non-ASCII chars
+        StringBuilder sb = new StringBuilder();
+        int codeLen = in.codePointCount(0, in.length());
+        int quoteChar = -1;
+        for (int i = 0; i < codeLen; i++) {
+            int code = in.codePointAt(i);
+            if (code == '"' || code == '\'') {
+                // If quote is escaped make sure to copy it
+                if (i > 0 && in.codePointAt(i - 1) == '\\') {
+                    sb.deleteCharAt(sb.length() - 1);
+                    sb.appendCodePoint(code);
+                    continue;
+                }
+                if (quoteChar != -1) {
+                    if (code == quoteChar) {
+                        // close quote, skip char
+                        quoteChar = -1;
+                    } else {
+                        sb.appendCodePoint(code);
+                    }
+                } else {
+                    // opening quote, skip char
+                    quoteChar = code;
+                }
+            } else {
+                sb.appendCodePoint(code);
+            }
+        }
+        return sb.toString();
+    }
+
+    private String getMainClassFromManifest() {
+        if (mainJarPath == null ||
+            input == null ) {
+            return null;
+        }
+
+        JarFile jf;
+        try {
+            File file = new File(input, mainJarPath);
+            if (!file.exists()) {
+                return null;
+            }
+            jf = new JarFile(file);
+            Manifest m = jf.getManifest();
+            Attributes attrs = (m != null) ? m.getMainAttributes() : null;
+            if (attrs != null) {
+                return attrs.getValue(Attributes.Name.MAIN_CLASS);
+            }
+        } catch (IOException ignore) {}
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/BasicBundlers.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.ServiceLoader;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * BasicBundlers
+ *
+ * A basic bundlers collection that loads the default bundlers.
+ * Loads the common bundlers.
+ * <UL>
+ *     <LI>Windows file image</LI>
+ *     <LI>Mac .app</LI>
+ *     <LI>Linux file image</LI>
+ *     <LI>Windows MSI</LI>
+ *     <LI>Windows EXE</LI>
+ *     <LI>Mac DMG</LI>
+ *     <LI>Mac PKG</LI>
+ *     <LI>Linux DEB</LI>
+ *     <LI>Linux RPM</LI>
+ *
+ * </UL>
+ */
+public class BasicBundlers implements Bundlers {
+
+    boolean defaultsLoaded = false;
+
+    private final Collection<Bundler> bundlers = new CopyOnWriteArrayList<>();
+
+    @Override
+    public Collection<Bundler> getBundlers() {
+        return Collections.unmodifiableCollection(bundlers);
+    }
+
+    @Override
+    public Collection<Bundler> getBundlers(String type) {
+        if (type == null) return Collections.emptySet();
+        switch (type) {
+            case "NONE":
+                return Collections.emptySet();
+            case "ALL":
+                return getBundlers();
+            default:
+                return Arrays.asList(getBundlers().stream()
+                        .filter(b -> type.equalsIgnoreCase(b.getBundleType()))
+                        .toArray(Bundler[]::new));
+        }
+    }
+
+    // Loads bundlers from the META-INF/services direct
+    @Override
+    public void loadBundlersFromServices(ClassLoader cl) {
+        ServiceLoader<Bundler> loader = ServiceLoader.load(Bundler.class, cl);
+        for (Bundler aLoader : loader) {
+            bundlers.add(aLoader);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/BundleParams.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+public class BundleParams {
+
+    final protected Map<String, ? super Object> params;
+
+    // RelativeFileSet
+    public static final String PARAM_APP_RESOURCES      = "appResources";
+
+    // String - Icon file name
+    public static final String PARAM_ICON               = "icon";
+
+    // String - Name of bundle file and native launcher
+    public static final String PARAM_NAME               = "name";
+
+    // String - application vendor, used by most of the bundlers
+    public static final String PARAM_VENDOR             = "vendor";
+
+    // String - email name and email, only used for debian */
+    public static final String PARAM_EMAIL              = "email";
+
+    // String - vendor <email>, only used for debian */
+    public static final String PARAM_MAINTAINER         = "maintainer";
+
+    /* String - Copyright. Used on Mac */
+    public static final String PARAM_COPYRIGHT          = "copyright";
+
+    // String - GUID on windows for MSI, CFBundleIdentifier on Mac
+    // If not compatible with requirements then bundler either do not bundle
+    // or autogenerate
+    public static final String PARAM_IDENTIFIER         = "identifier";
+
+    /* boolean - shortcut preferences */
+    public static final String PARAM_SHORTCUT           = "shortcutHint";
+    // boolean - menu shortcut preference
+    public static final String PARAM_MENU               = "menuHint";
+
+    // String - Application version. Format may differ for different bundlers
+    public static final String PARAM_VERSION            = "appVersion";
+
+    // String - Application release. Used on Linux.
+    public static final String PARAM_RELEASE            = "appRelease";
+
+    // String - Optional application description. Used by MSI and on Linux
+    public static final String PARAM_DESCRIPTION        = "description";
+
+    // String - License type. Needed on Linux (rpm)
+    public static final String PARAM_LICENSE_TYPE       = "licenseType";
+
+    // String - File with license. Format is OS/bundler specific
+    public static final String PARAM_LICENSE_FILE       = "licenseFile";
+
+    // String Main application class.
+    // Not used directly but used to derive default values
+    public static final String PARAM_APPLICATION_CLASS  = "applicationClass";
+
+    // boolean - Adds a dialog to let the user choose a directory
+    // where the product will be installed.
+    public static final String PARAM_INSTALLDIR_CHOOSER = "installdirChooser";
+
+    /**
+     * create a new bundle with all default values
+     */
+    public BundleParams() {
+        params = new HashMap<>();
+    }
+
+    /**
+     * Create a bundle params with a copy of the params
+     * @param params map of initial parameters to be copied in.
+     */
+    public BundleParams(Map<String, ?> params) {
+        this.params = new HashMap<>(params);
+    }
+
+    public void addAllBundleParams(Map<String, ? super Object> params) {
+        this.params.putAll(params);
+    }
+
+    // NOTE: we do not care about application parameters here
+    // as they will be embeded into jar file manifest and
+    // java launcher will take care of them!
+
+    public Map<String, ? super Object> getBundleParamsAsMap() {
+        return new HashMap<>(params);
+    }
+
+    public String getName() {
+        return APP_NAME.fetchFrom(params);
+    }
+
+    public void setAppResourcesList(
+            List<jdk.incubator.jpackage.internal.RelativeFileSet> rfs) {
+        putUnlessNull(APP_RESOURCES_LIST.getID(), rfs);
+    }
+
+    private void putUnlessNull(String param, Object value) {
+        if (value != null) {
+            params.put(param, value);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Bundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Bundler
+ *
+ * The basic interface implemented by all Bundlers.
+ */
+public interface Bundler {
+    /**
+     * @return User Friendly name of this bundler.
+     */
+    String getName();
+
+    /**
+     * @return Command line identifier of the bundler.  Should be unique.
+     */
+    String getID();
+
+    /**
+     * @return The bundle type of the bundle that is created by this bundler.
+     */
+    String getBundleType();
+
+    /**
+     * Determines if this bundler will execute with the given parameters.
+     *
+     * @param params The parameters to be validate.  Validation may modify
+     *               the map, so if you are going to be using the same map
+     *               across multiple bundlers you should pass in a deep copy.
+     * @return true if valid
+     * @throws ConfigException If the configuration params are incorrect.  The
+     *         exception may contain advice on how to modify the params map
+     *         to make it valid.
+     */
+    public boolean validate(Map<String, ? super Object> params)
+            throws ConfigException;
+
+    /**
+     * Creates a bundle from existing content.
+     *
+     * If a call to {@link #validate(java.util.Map)} date} returns true with
+     * the parameters map, then you can expect a valid output.
+     * However if an exception was thrown out of validate or it returned
+     * false then you should not expect sensible results from this call.
+     * It may or may not return a value, and it may or may not throw an
+     * exception.  But any output should not be considered valid or sane.
+     *
+     * @param params The Bundle parameters,
+     *               Keyed by the id from the ParamInfo.  Execution may
+     *               modify the map, so if you are going to be using the
+     *               same map across multiple bundlers you should pass
+     *               in a deep copy.
+     * @param outputParentDir
+     *   The parent dir that the returned bundle will be placed in.
+     * @return The resulting bundled file
+     *
+     * For a bundler that produces a single artifact file this will be the
+     * location of that artifact (.exe file, .deb file, etc)
+     *
+     * For a bundler that produces a specific directory format output this will
+     * be the location of that specific directory (.app file, etc).
+     *
+     * For a bundler that produce multiple files, this will be a parent
+     * directory of those files (linux and windows images), whose name is not
+     * relevant to the result.
+     *
+     * @throws java.lang.IllegalArgumentException for any of the following
+     * reasons:
+     *  <ul>
+     *      <li>A required parameter is not found in the params list, for
+     *      example missing the main class.</li>
+     *      <li>A parameter has the wrong type of an object, for example a
+     *      String where a File is required</li>
+     *      <li>Bundler specific incompatibilities with the parameters, for
+     *      example a bad version number format or an application id with
+     *      forward slashes.</li>
+     *  </ul>
+     */
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) throws PackagerException;
+
+     /**
+     * Removes temporary files that are used for bundling.
+     */
+    public void cleanup(Map<String, ? super Object> params);
+
+    /**
+     * Returns "true" if this bundler is supported on current platform.
+     */
+    public boolean supported(boolean runtimeInstaller);
+
+    /**
+     * Returns "true" if this bundler is he default for the current platform.
+     */
+    public boolean isDefault();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/BundlerParamInfo.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * BundlerParamInfo<T>
+ *
+ * A BundlerParamInfo encapsulates an individual bundler parameter of type <T>.
+ */
+class BundlerParamInfo<T> {
+
+    /**
+     * The command line and hashmap name of the parameter
+     */
+    String id;
+
+    /**
+     * Type of the parameter
+     */
+    Class<T> valueType;
+
+    /**
+     * Indicates if value was set using default value function
+     */
+    boolean isDefaultValue;
+
+    /**
+     * If the value is not set, and no fallback value is found,
+     * the parameter uses the value returned by the producer.
+     */
+    Function<Map<String, ? super Object>, T> defaultValueFunction;
+
+    /**
+     * An optional string converter for command line arguments.
+     */
+    BiFunction<String, Map<String, ? super Object>, T> stringConverter;
+
+    String getID() {
+        return id;
+    }
+
+    Class<T> getValueType() {
+        return valueType;
+    }
+
+    boolean getIsDefaultValue() {
+        return isDefaultValue;
+    }
+
+    Function<Map<String, ? super Object>, T> getDefaultValueFunction() {
+        return defaultValueFunction;
+    }
+
+    BiFunction<String, Map<String, ? super Object>,T>
+            getStringConverter() {
+        return stringConverter;
+    }
+
+    @SuppressWarnings("unchecked")
+    final T fetchFrom(Map<String, ? super Object> params) {
+        return fetchFrom(params, true);
+    }
+
+    @SuppressWarnings("unchecked")
+    final T fetchFrom(Map<String, ? super Object> params,
+            boolean invokeDefault) {
+        Object o = params.get(getID());
+        if (o instanceof String && getStringConverter() != null) {
+            return getStringConverter().apply((String)o, params);
+        }
+
+        Class<T> klass = getValueType();
+        if (klass.isInstance(o)) {
+            return (T) o;
+        }
+        if (o != null) {
+            throw new IllegalArgumentException("Param " + getID()
+                    + " should be of type " + getValueType()
+                    + " but is a " + o.getClass());
+        }
+        if (params.containsKey(getID())) {
+            // explicit nulls are allowed
+            return null;
+        }
+
+        if (invokeDefault && (getDefaultValueFunction() != null)) {
+            T result =  getDefaultValueFunction().apply(params);
+            if (result != null) {
+                params.put(getID(), result);
+                isDefaultValue = true;
+            }
+            return result;
+        }
+
+        // ultimate fallback
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Bundlers.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+/**
+ * Bundlers
+ *
+ * The interface implemented by BasicBundlers
+ */
+public interface Bundlers {
+
+    /**
+     * This convenience method will call
+     * {@link #createBundlersInstance(ClassLoader)}
+     * with the classloader that this Bundlers is loaded from.
+     *
+     * @return an instance of Bundlers loaded and configured from
+     *         the current ClassLoader.
+     */
+    public static Bundlers createBundlersInstance() {
+        return createBundlersInstance(Bundlers.class.getClassLoader());
+    }
+
+    /**
+     * This convenience method will automatically load a Bundlers instance
+     * from either META-INF/services or the default
+     * {@link BasicBundlers} if none are found in
+     * the services meta-inf.
+     *
+     * After instantiating the bundlers instance it will load the default
+     * bundlers via {@link #loadDefaultBundlers()} as well as requesting
+     * the services loader to load any other bundelrs via
+     * {@link #loadBundlersFromServices(ClassLoader)}.
+
+     *
+     * @param servicesClassLoader the classloader to search for
+     *                            META-INF/service registered bundlers
+     * @return an instance of Bundlers loaded and configured from
+     *         the specified ClassLoader
+     */
+    public static Bundlers createBundlersInstance(
+            ClassLoader servicesClassLoader) {
+        ServiceLoader<Bundlers> bundlersLoader =
+                ServiceLoader.load(Bundlers.class, servicesClassLoader);
+        Bundlers bundlers = null;
+        Iterator<Bundlers> iter = bundlersLoader.iterator();
+        if (iter.hasNext()) {
+            bundlers = iter.next();
+        }
+        if (bundlers == null) {
+            bundlers = new BasicBundlers();
+        }
+
+        bundlers.loadBundlersFromServices(servicesClassLoader);
+        return bundlers;
+    }
+
+    /**
+     * Returns all of the preconfigured, requested, and manually
+     * configured bundlers loaded with this instance.
+     *
+     * @return  a read-only collection of the requested bundlers
+     */
+    Collection<Bundler> getBundlers();
+
+    /**
+     * Returns all of the preconfigured, requested, and manually
+     * configured bundlers loaded with this instance that are of
+     * a specific BundleType, such as disk images, installers, or
+     * remote installers.
+     *
+     * @return a read-only collection of the requested bundlers
+     */
+    Collection<Bundler> getBundlers(String type);
+
+    /**
+     * Loads bundlers from the META-INF/services directly.
+     *
+     * This method is called from the
+     * {@link #createBundlersInstance(ClassLoader)}
+     * and {@link #createBundlersInstance()} methods.
+     */
+    void loadBundlersFromServices(ClassLoader cl);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/CLIHelp.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, 2019, 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.incubator.jpackage.internal;
+
+import java.util.ResourceBundle;
+import java.io.File;
+import java.text.MessageFormat;
+
+
+/**
+ * CLIHelp
+ *
+ * Generate and show the command line interface help message(s).
+ */
+public class CLIHelp {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.HelpResources");
+
+    // generates --help for jpackage's CLI
+    public static void showHelp(boolean noArgs) {
+
+        if (noArgs) {
+            Log.info(I18N.getString("MSG_Help_no_args"));
+        } else {
+            Platform platform = (Log.isVerbose()) ?
+                    Platform.UNKNOWN : Platform.getPlatform();
+            String types;
+            String pLaunchOptions;
+            String pInstallOptions;
+            String pInstallDir;
+            switch (platform) {
+                case MAC:
+                    types = "{\"app-image\", \"dmg\", \"pkg\"}";
+                    pLaunchOptions = I18N.getString("MSG_Help_mac_launcher");
+                    pInstallOptions = "";
+                    pInstallDir
+                            = I18N.getString("MSG_Help_mac_linux_install_dir");
+                    break;
+                case LINUX:
+                    types = "{\"app-image\", \"rpm\", \"deb\"}";
+                    pLaunchOptions = "";
+                    pInstallOptions = I18N.getString("MSG_Help_linux_install");
+                    pInstallDir
+                            = I18N.getString("MSG_Help_mac_linux_install_dir");
+                    break;
+                case WINDOWS:
+                    types = "{\"app-image\", \"exe\", \"msi\"}";
+                    pLaunchOptions = I18N.getString("MSG_Help_win_launcher");
+                    pInstallOptions = I18N.getString("MSG_Help_win_install");
+                    pInstallDir
+                            = I18N.getString("MSG_Help_win_install_dir");
+                    break;
+                default:
+                    types = "{\"app-image\", \"exe\", \"msi\", \"rpm\", \"deb\", \"pkg\", \"dmg\"}";
+                    pLaunchOptions = I18N.getString("MSG_Help_win_launcher")
+                            + I18N.getString("MSG_Help_mac_launcher");
+                    pInstallOptions = I18N.getString("MSG_Help_win_install")
+                            + I18N.getString("MSG_Help_linux_install");
+                    pInstallDir
+                            = I18N.getString("MSG_Help_default_install_dir");
+                    break;
+            }
+            Log.info(MessageFormat.format(I18N.getString("MSG_Help"),
+                    File.pathSeparator, types, pLaunchOptions,
+                    pInstallOptions, pInstallDir));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ConfigException.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+public class ConfigException extends Exception {
+    private static final long serialVersionUID = 1L;
+    final String advice;
+
+    public ConfigException(String msg, String advice) {
+        super(msg);
+        this.advice = advice;
+    }
+
+    public ConfigException(String msg, String advice, Exception cause) {
+        super(msg, cause);
+        this.advice = advice;
+    }
+
+    public ConfigException(Exception cause) {
+        super(cause);
+        this.advice = null;
+    }
+
+    public String getAdvice() {
+        return advice;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/DeployParams.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2011, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.InvalidPathException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ * DeployParams
+ *
+ * This class is generated and used in Arguments.processArguments() as
+ * intermediate step in generating the BundleParams and ultimately the Bundles
+ */
+public class DeployParams {
+
+    final List<RelativeFileSet> resources = new ArrayList<>();
+
+    String targetFormat = null; // means default type for this platform
+
+    File outdir = null;
+
+    // raw arguments to the bundler
+    Map<String, ? super Object> bundlerArguments = new LinkedHashMap<>();
+
+    public void setOutput(File output) {
+        outdir = output;
+    }
+
+    static class Template {
+        File in;
+        File out;
+
+        Template(File in, File out) {
+            this.in = in;
+            this.out = out;
+        }
+    }
+
+    // we need to expand as in some cases
+    // (most notably jpackage)
+    // we may get "." as filename and assumption is we include
+    // everything in the given folder
+    // (IOUtils.copyfiles() have recursive behavior)
+    List<File> expandFileset(File root) {
+        List<File> files = new LinkedList<>();
+        if (!Files.isSymbolicLink(root.toPath())) {
+            if (root.isDirectory()) {
+                File[] children = root.listFiles();
+                if (children != null) {
+                    for (File f : children) {
+                        files.addAll(expandFileset(f));
+                    }
+                }
+            } else {
+                files.add(root);
+            }
+        }
+        return files;
+    }
+
+    public void addResource(File baseDir, String path) {
+        addResource(baseDir, new File(baseDir, path));
+    }
+
+    public void addResource(File baseDir, File file) {
+        // normalize initial file
+        // to strip things like "." in the path
+        // or it can confuse symlink detection logic
+        file = file.getAbsoluteFile();
+
+        if (baseDir == null) {
+            baseDir = file.getParentFile();
+        }
+        resources.add(new RelativeFileSet(
+                baseDir, new LinkedHashSet<>(expandFileset(file))));
+    }
+
+    void setClasspath(String mainJarPath) {
+        String classpath;
+        // we want main jar first on the classpath
+        if (mainJarPath != null) {
+            classpath = mainJarPath + File.pathSeparator;
+        } else {
+            classpath = "";
+        }
+        for (RelativeFileSet resource : resources) {
+             for (String file : resource.getIncludedFiles()) {
+                 if (file.endsWith(".jar")) {
+                     if (!file.equals(mainJarPath)) {
+                         classpath += file + File.pathSeparator;
+                     }
+                 }
+             }
+        }
+        addBundleArgument(
+                StandardBundlerParam.CLASSPATH.getID(), classpath);
+    }
+
+    static void validateName(String s, boolean forApp)
+            throws PackagerException {
+
+        String exceptionKey = forApp ?
+            "ERR_InvalidAppName" : "ERR_InvalidSLName";
+
+        if (s == null) {
+            if (forApp) {
+                return;
+            } else {
+                throw new PackagerException(exceptionKey, s);
+            }
+        }
+        if (s.length() == 0 || s.charAt(s.length() - 1) == '\\') {
+            throw new PackagerException(exceptionKey, s);
+        }
+        try {
+            // name must be valid path element for this file system
+            Path p = (new File(s)).toPath();
+            // and it must be a single name element in a path
+            if (p.getNameCount() != 1) {
+                throw new PackagerException(exceptionKey, s);
+            }
+        } catch (InvalidPathException ipe) {
+            throw new PackagerException(ipe, exceptionKey, s);
+        }
+
+        for (int i = 0; i < s.length(); i++) {
+            char a = s.charAt(i);
+            // We check for ASCII codes first which we accept. If check fails,
+            // check if it is acceptable extended ASCII or unicode character.
+            if (a < ' ' || a > '~') {
+                // Accept anything else including special chars like copyright
+                // symbols. Note: space will be included by ASCII check above,
+                // but other whitespace like tabs or new line will be rejected.
+                if (Character.isISOControl(a)  ||
+                        Character.isWhitespace(a)) {
+                    throw new PackagerException(exceptionKey, s);
+                }
+            } else if (a == '"' || a == '%') {
+                throw new PackagerException(exceptionKey, s);
+            }
+        }
+    }
+
+    public void validate() throws PackagerException {
+        boolean hasModule = (bundlerArguments.get(
+                Arguments.CLIOptions.MODULE.getId()) != null);
+        boolean hasAppImage = (bundlerArguments.get(
+                Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId()) != null);
+        boolean hasClass = (bundlerArguments.get(
+                Arguments.CLIOptions.APPCLASS.getId()) != null);
+        boolean hasMain = (bundlerArguments.get(
+                Arguments.CLIOptions.MAIN_JAR.getId()) != null);
+        boolean hasRuntimeImage = (bundlerArguments.get(
+                Arguments.CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId()) != null);
+        boolean hasInput = (bundlerArguments.get(
+                Arguments.CLIOptions.INPUT.getId()) != null);
+        boolean hasModulePath = (bundlerArguments.get(
+                Arguments.CLIOptions.MODULE_PATH.getId()) != null);
+        boolean runtimeInstaller = !isTargetAppImage() &&
+                !hasAppImage && !hasModule && !hasMain && hasRuntimeImage;
+
+        if (isTargetAppImage()) {
+            // Module application requires --runtime-image or --module-path
+            if (hasModule) {
+                if (!hasModulePath && !hasRuntimeImage) {
+                    throw new PackagerException("ERR_MissingArgument",
+                            "--runtime-image or --module-path");
+                }
+            } else {
+                if (!hasInput) {
+                    throw new PackagerException(
+                           "ERR_MissingArgument", "--input");
+                }
+            }
+        } else {
+            if (!runtimeInstaller) {
+                if (hasModule) {
+                    if (!hasModulePath && !hasRuntimeImage && !hasAppImage) {
+                        throw new PackagerException("ERR_MissingArgument",
+                            "--runtime-image, --module-path or --app-image");
+                    }
+                } else {
+                    if (!hasInput && !hasAppImage) {
+                        throw new PackagerException("ERR_MissingArgument",
+                                "--input or --app-image");
+                    }
+                }
+            }
+        }
+
+        // if bundling non-modular image, or installer without app-image
+        // then we need some resources and a main class
+        if (!hasModule && !hasAppImage && !runtimeInstaller) {
+            if (resources.isEmpty()) {
+                throw new PackagerException("ERR_MissingAppResources");
+            }
+            if (!hasMain) {
+                throw new PackagerException("ERR_MissingArgument",
+                        "--main-jar");
+            }
+        }
+
+        String name = (String)bundlerArguments.get(
+                Arguments.CLIOptions.NAME.getId());
+        validateName(name, true);
+
+        // Validate app image if set
+        String appImage = (String)bundlerArguments.get(
+                Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId());
+        if (appImage != null) {
+            File appImageDir = new File(appImage);
+            if (!appImageDir.exists() || appImageDir.list().length == 0) {
+                throw new PackagerException("ERR_AppImageNotExist", appImage);
+            }
+        }
+
+        // Validate temp dir
+        String root = (String)bundlerArguments.get(
+                Arguments.CLIOptions.TEMP_ROOT.getId());
+        if (root != null) {
+            String [] contents = (new File(root)).list();
+
+            if (contents != null && contents.length > 0) {
+                throw new PackagerException("ERR_BuildRootInvalid", root);
+            }
+        }
+
+        // Validate license file if set
+        String license = (String)bundlerArguments.get(
+                Arguments.CLIOptions.LICENSE_FILE.getId());
+        if (license != null) {
+            File licenseFile = new File(license);
+            if (!licenseFile.exists()) {
+                throw new PackagerException("ERR_LicenseFileNotExit");
+            }
+        }
+    }
+
+    void setTargetFormat(String t) {
+        targetFormat = t;
+    }
+
+    String getTargetFormat() {
+        return targetFormat;
+    }
+
+    boolean isTargetAppImage() {
+        return ("app-image".equals(targetFormat));
+    }
+
+    private static final Set<String> multi_args = new TreeSet<>(Arrays.asList(
+            StandardBundlerParam.JAVA_OPTIONS.getID(),
+            StandardBundlerParam.ARGUMENTS.getID(),
+            StandardBundlerParam.MODULE_PATH.getID(),
+            StandardBundlerParam.ADD_MODULES.getID(),
+            StandardBundlerParam.LIMIT_MODULES.getID(),
+            StandardBundlerParam.FILE_ASSOCIATIONS.getID()
+    ));
+
+    @SuppressWarnings("unchecked")
+    public void addBundleArgument(String key, Object value) {
+        // special hack for multi-line arguments
+        if (multi_args.contains(key)) {
+            Object existingValue = bundlerArguments.get(key);
+            if (existingValue instanceof String && value instanceof String) {
+                String delim = "\n\n";
+                if (key.equals(StandardBundlerParam.MODULE_PATH.getID())) {
+                    delim = File.pathSeparator;
+                } else if (key.equals(
+                        StandardBundlerParam.ADD_MODULES.getID())) {
+                    delim = ",";
+                }
+                bundlerArguments.put(key, existingValue + delim + value);
+            } else if (existingValue instanceof List && value instanceof List) {
+                ((List)existingValue).addAll((List)value);
+            } else if (existingValue instanceof Map &&
+                value instanceof String && ((String)value).contains("=")) {
+                String[] mapValues = ((String)value).split("=", 2);
+                ((Map)existingValue).put(mapValues[0], mapValues[1]);
+            } else {
+                bundlerArguments.put(key, value);
+            }
+        } else {
+            bundlerArguments.put(key, value);
+        }
+    }
+
+    BundleParams getBundleParams() {
+        BundleParams bundleParams = new BundleParams();
+
+        // construct app resources relative to destination folder!
+        bundleParams.setAppResourcesList(resources);
+
+        Map<String, String> unescapedHtmlParams = new TreeMap<>();
+        Map<String, String> escapedHtmlParams = new TreeMap<>();
+
+        // check for collisions
+        TreeSet<String> keys = new TreeSet<>(bundlerArguments.keySet());
+        keys.retainAll(bundleParams.getBundleParamsAsMap().keySet());
+
+        if (!keys.isEmpty()) {
+            throw new RuntimeException("Deploy Params and Bundler Arguments "
+                    + "overlap in the following values:" + keys.toString());
+        }
+
+        bundleParams.addAllBundleParams(bundlerArguments);
+
+        return bundleParams;
+    }
+
+    @Override
+    public String toString() {
+        return "DeployParams {" + "output: " + outdir
+                + " resources: {" + resources + "}}";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/DottedVersion.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+/**
+ * Dotted numeric version string.
+ * E.g.: 1.0.37, 10, 0.5
+ */
+class DottedVersion implements Comparable<String> {
+
+    public DottedVersion(String version) {
+        greedy = true;
+        components = parseVersionString(version, greedy);
+        value = version;
+    }
+
+    private DottedVersion(String version, boolean greedy) {
+        this.greedy = greedy;
+        components = parseVersionString(version, greedy);
+        value = version;
+    }
+
+    public static DottedVersion greedy(String version) {
+        return new DottedVersion(version);
+    }
+
+    public static DottedVersion lazy(String version) {
+        return new DottedVersion(version, false);
+    }
+
+    @Override
+    public int compareTo(String o) {
+        int result = 0;
+        int[] otherComponents = parseVersionString(o, greedy);
+        for (int i = 0; i < Math.min(components.length, otherComponents.length)
+                && result == 0; ++i) {
+            result = components[i] - otherComponents[i];
+        }
+
+        if (result == 0) {
+            result = components.length - otherComponents.length;
+        }
+
+        return result;
+    }
+
+    private static int[] parseVersionString(String version, boolean greedy) {
+        Objects.requireNonNull(version);
+        if (version.isEmpty()) {
+            if (!greedy) {
+                return new int[] {0};
+            }
+            throw new IllegalArgumentException("Version may not be empty string");
+        }
+
+        int lastNotZeroIdx = -1;
+        List<Integer> components = new ArrayList<>();
+        for (var component : version.split("\\.", -1)) {
+            if (component.isEmpty()) {
+                if (!greedy) {
+                    break;
+                }
+
+                throw new IllegalArgumentException(String.format(
+                        "Version [%s] contains a zero lenght component", version));
+            }
+
+            if (!DIGITS.matcher(component).matches()) {
+                // Catch "+N" and "-N"  cases.
+                if (!greedy) {
+                    break;
+                }
+
+                throw new IllegalArgumentException(String.format(
+                        "Version [%s] contains invalid component [%s]", version,
+                        component));
+            }
+
+            final int num;
+            try {
+                num = Integer.parseInt(component);
+            } catch (NumberFormatException ex) {
+                if (!greedy) {
+                    break;
+                }
+
+                throw ex;
+            }
+
+            if (num != 0) {
+                lastNotZeroIdx = components.size();
+            }
+            components.add(num);
+        }
+
+        if (lastNotZeroIdx + 1 != components.size()) {
+            // Strip trailing zeros.
+            components = components.subList(0, lastNotZeroIdx + 1);
+        }
+
+        if (components.isEmpty()) {
+            components.add(0);
+        }
+        return components.stream().mapToInt(Integer::intValue).toArray();
+    }
+
+    @Override
+    public String toString() {
+        return value;
+    }
+
+    final private int[] components;
+    final private String value;
+    final private boolean greedy;
+
+    private static final Pattern DIGITS = Pattern.compile("\\d+");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Executor.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+final public class Executor {
+
+    Executor() {
+    }
+
+    Executor setOutputConsumer(Consumer<Stream<String>> v) {
+        outputConsumer = v;
+        return this;
+    }
+
+    Executor saveOutput(boolean v) {
+        saveOutput = v;
+        return this;
+    }
+
+    Executor setProcessBuilder(ProcessBuilder v) {
+        pb = v;
+        return this;
+    }
+
+    Executor setCommandLine(String... cmdline) {
+        return setProcessBuilder(new ProcessBuilder(cmdline));
+    }
+
+    List<String> getOutput() {
+        return output;
+    }
+
+    Executor executeExpectSuccess() throws IOException {
+        int ret = execute();
+        if (0 != ret) {
+            throw new IOException(
+                    String.format("Command %s exited with %d code",
+                            createLogMessage(pb), ret));
+        }
+        return this;
+    }
+
+    int execute() throws IOException {
+        output = null;
+
+        boolean needProcessOutput = outputConsumer != null || Log.isVerbose() || saveOutput;
+        if (needProcessOutput) {
+            pb.redirectErrorStream(true);
+        } else {
+            // We are not going to read process output, so need to notify
+            // ProcessBuilder about this. Otherwise some processes might just
+            // hang up (`ldconfig -p`).
+            pb.redirectError(ProcessBuilder.Redirect.DISCARD);
+            pb.redirectOutput(ProcessBuilder.Redirect.DISCARD);
+        }
+
+        Log.verbose(String.format("Running %s", createLogMessage(pb)));
+        Process p = pb.start();
+
+        if (needProcessOutput) {
+            try (var br = new BufferedReader(new InputStreamReader(
+                    p.getInputStream()))) {
+                final List<String> savedOutput;
+                // Need to save output if explicitely requested (saveOutput=true) or
+                // if will be used used by multiple consumers
+                if ((outputConsumer != null && Log.isVerbose()) || saveOutput) {
+                    savedOutput = br.lines().collect(Collectors.toList());
+                    if (saveOutput) {
+                        output = savedOutput;
+                    }
+                } else {
+                    savedOutput = null;
+                }
+
+                Supplier<Stream<String>> outputStream = () -> {
+                    if (savedOutput != null) {
+                        return savedOutput.stream();
+                    }
+                    return br.lines();
+                };
+
+                if (Log.isVerbose()) {
+                    outputStream.get().forEach(Log::verbose);
+                }
+
+                if (outputConsumer != null) {
+                    outputConsumer.accept(outputStream.get());
+                }
+
+                if (savedOutput == null) {
+                    // For some processes on Linux if the output stream
+                    // of the process is opened but not consumed, the process
+                    // would exit with code 141.
+                    // It turned out that reading just a single line of process
+                    // output fixes the problem, but let's process
+                    // all of the output, just in case.
+                    br.lines().forEach(x -> {});
+                }
+            }
+        }
+
+        try {
+            return p.waitFor();
+        } catch (InterruptedException ex) {
+            Log.verbose(ex);
+            throw new RuntimeException(ex);
+        }
+    }
+
+    static Executor of(String... cmdline) {
+        return new Executor().setCommandLine(cmdline);
+    }
+
+    static Executor of(ProcessBuilder pb) {
+        return new Executor().setProcessBuilder(pb);
+    }
+
+    private static String createLogMessage(ProcessBuilder pb) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(String.format("%s", pb.command()));
+        if (pb.directory() != null) {
+            sb.append(String.format("in %s", pb.directory().getAbsolutePath()));
+        }
+        return sb.toString();
+    }
+
+    private ProcessBuilder pb;
+    private boolean saveOutput;
+    private List<String> output;
+    private Consumer<Stream<String>> outputConsumer;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/FileAssociation.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.stream.Collectors;
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+final class FileAssociation {
+    void verify() {
+        if (extensions.isEmpty()) {
+            Log.error(I18N.getString(
+                    "message.creating-association-with-null-extension"));
+        }
+    }
+
+    static List<FileAssociation> fetchFrom(Map<String, ? super Object> params) {
+        String launcherName = APP_NAME.fetchFrom(params);
+
+        return FILE_ASSOCIATIONS.fetchFrom(params).stream().filter(
+                Objects::nonNull).map(fa -> {
+                    FileAssociation assoc = new FileAssociation();
+
+                    assoc.launcherPath = Path.of(launcherName);
+                    assoc.description = FA_DESCRIPTION.fetchFrom(fa);
+                    assoc.extensions = Optional.ofNullable(
+                            FA_EXTENSIONS.fetchFrom(fa)).orElse(Collections.emptyList());
+                    assoc.mimeTypes = Optional.ofNullable(
+                            FA_CONTENT_TYPE.fetchFrom(fa)).orElse(Collections.emptyList());
+
+                    File icon = FA_ICON.fetchFrom(fa);
+                    if (icon != null) {
+                        assoc.iconPath = icon.toPath();
+                    }
+
+                    return assoc;
+                }).collect(Collectors.toList());
+    }
+
+    Path launcherPath;
+    Path iconPath;
+    List<String> mimeTypes;
+    List<String> extensions;
+    String description;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/I18N.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.util.ResourceBundle;
+
+class I18N {
+
+    static String getString(String key) {
+        if (PLATFORM.containsKey(key)) {
+            return PLATFORM.getString(key);
+        }
+        return SHARED.getString(key);
+    }
+
+    private static final ResourceBundle SHARED = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MainResources");
+
+    private static final ResourceBundle PLATFORM;
+
+    static {
+        if (Platform.isLinux()) {
+            PLATFORM = ResourceBundle.getBundle(
+                    "jdk.incubator.jpackage.internal.resources.LinuxResources");
+        } else if (Platform.isWindows()) {
+            PLATFORM = ResourceBundle.getBundle(
+                    "jdk.incubator.jpackage.internal.resources.WinResources");
+        } else if (Platform.isMac()) {
+            PLATFORM = ResourceBundle.getBundle(
+                    "jdk.incubator.jpackage.internal.resources.MacResources");
+        } else {
+            throw new IllegalStateException("Unknwon platform");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/IOUtils.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.*;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.nio.channels.FileChannel;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.*;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+/**
+ * IOUtils
+ *
+ * A collection of static utility methods.
+ */
+public class IOUtils {
+
+    public static void deleteRecursive(File path) throws IOException {
+        if (!path.exists()) {
+            return;
+        }
+        Path directory = path.toPath();
+        Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult visitFile(Path file,
+                            BasicFileAttributes attr) throws IOException {
+                if (Platform.getPlatform() == Platform.WINDOWS) {
+                    Files.setAttribute(file, "dos:readonly", false);
+                }
+                Files.delete(file);
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult preVisitDirectory(Path dir,
+                            BasicFileAttributes attr) throws IOException {
+                if (Platform.getPlatform() == Platform.WINDOWS) {
+                    Files.setAttribute(dir, "dos:readonly", false);
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir, IOException e)
+                            throws IOException {
+                Files.delete(dir);
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    public static void copyRecursive(Path src, Path dest) throws IOException {
+        copyRecursive(src, dest, List.of());
+    }
+
+    public static void copyRecursive(Path src, Path dest,
+            final List<String> excludes) throws IOException {
+        Files.walkFileTree(src, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult preVisitDirectory(final Path dir,
+                    final BasicFileAttributes attrs) throws IOException {
+                if (excludes.contains(dir.toFile().getName())) {
+                    return FileVisitResult.SKIP_SUBTREE;
+                } else {
+                    Files.createDirectories(dest.resolve(src.relativize(dir)));
+                    return FileVisitResult.CONTINUE;
+                }
+            }
+
+            @Override
+            public FileVisitResult visitFile(final Path file,
+                    final BasicFileAttributes attrs) throws IOException {
+                if (!excludes.contains(file.toFile().getName())) {
+                    Files.copy(file, dest.resolve(src.relativize(file)));
+                }
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    public static void copyFile(File sourceFile, File destFile)
+            throws IOException {
+        destFile.getParentFile().mkdirs();
+
+        //recreate the file as existing copy may have weird permissions
+        destFile.delete();
+        destFile.createNewFile();
+
+        try (FileChannel source = new FileInputStream(sourceFile).getChannel();
+            FileChannel destination =
+                    new FileOutputStream(destFile).getChannel()) {
+
+            if (destination != null && source != null) {
+                destination.transferFrom(source, 0, source.size());
+            }
+        }
+
+        //preserve executable bit!
+        if (sourceFile.canExecute()) {
+            destFile.setExecutable(true, false);
+        }
+        if (!sourceFile.canWrite()) {
+            destFile.setReadOnly();
+        }
+        destFile.setReadable(true, false);
+    }
+
+    // run "launcher paramfile" in the directory where paramfile is kept
+    public static void run(String launcher, File paramFile)
+            throws IOException {
+        if (paramFile != null && paramFile.exists()) {
+            ProcessBuilder pb =
+                    new ProcessBuilder(launcher, paramFile.getName());
+            pb = pb.directory(paramFile.getParentFile());
+            exec(pb);
+        }
+    }
+
+    public static void exec(ProcessBuilder pb)
+            throws IOException {
+        exec(pb, false, null);
+    }
+
+    static void exec(ProcessBuilder pb, boolean testForPresenseOnly,
+            PrintStream consumer) throws IOException {
+        List<String> output = new ArrayList<>();
+        Executor exec = Executor.of(pb).setOutputConsumer(lines -> {
+            lines.forEach(output::add);
+            if (consumer != null) {
+                output.forEach(consumer::println);
+            }
+        });
+
+        if (testForPresenseOnly) {
+            exec.execute();
+        } else {
+            exec.executeExpectSuccess();
+        }
+    }
+
+    public static int getProcessOutput(List<String> result, String... args)
+            throws IOException, InterruptedException {
+
+        ProcessBuilder pb = new ProcessBuilder(args);
+
+        final Process p = pb.start();
+
+        List<String> list = new ArrayList<>();
+
+        final BufferedReader in =
+                new BufferedReader(new InputStreamReader(p.getInputStream()));
+        final BufferedReader err =
+                new BufferedReader(new InputStreamReader(p.getErrorStream()));
+
+        Thread t = new Thread(() -> {
+            try {
+                String line;
+                while ((line = in.readLine()) != null) {
+                    list.add(line);
+                }
+            } catch (IOException ioe) {
+                Log.verbose(ioe);
+            }
+
+            try {
+                String line;
+                while ((line = err.readLine()) != null) {
+                    Log.error(line);
+                }
+            } catch (IOException ioe) {
+                  Log.verbose(ioe);
+            }
+        });
+        t.setDaemon(true);
+        t.start();
+
+        int ret = p.waitFor();
+
+        result.clear();
+        result.addAll(list);
+
+        return ret;
+    }
+
+    static void writableOutputDir(Path outdir) throws PackagerException {
+        File file = outdir.toFile();
+
+        if (!file.isDirectory() && !file.mkdirs()) {
+            throw new PackagerException("error.cannot-create-output-dir",
+                    file.getAbsolutePath());
+        }
+        if (!file.canWrite()) {
+            throw new PackagerException("error.cannot-write-to-output-dir",
+                    file.getAbsolutePath());
+        }
+    }
+
+    public static Path replaceSuffix(Path path, String suffix) {
+        Path parent = path.getParent();
+        String filename = path.getFileName().toString().replaceAll("\\.[^.]*$", "")
+                + Optional.ofNullable(suffix).orElse("");
+        return parent != null ? parent.resolve(filename) : Path.of(filename);
+    }
+
+    public static Path addSuffix(Path path, String suffix) {
+        Path parent = path.getParent();
+        String filename = path.getFileName().toString() + suffix;
+        return parent != null ? parent.resolve(filename) : Path.of(filename);
+    }
+
+    public static String getSuffix(Path path) {
+        String filename = replaceSuffix(path.getFileName(), null).toString();
+        return path.getFileName().toString().substring(filename.length());
+    }
+
+    @FunctionalInterface
+    public static interface XmlConsumer {
+        void accept(XMLStreamWriter xml) throws IOException, XMLStreamException;
+    }
+
+    public static void createXml(Path dstFile, XmlConsumer xmlConsumer) throws
+            IOException {
+        XMLOutputFactory xmlFactory = XMLOutputFactory.newInstance();
+        try (Writer w = Files.newBufferedWriter(dstFile)) {
+            // Wrap with pretty print proxy
+            XMLStreamWriter xml = (XMLStreamWriter) Proxy.newProxyInstance(
+                    XMLStreamWriter.class.getClassLoader(), new Class<?>[]{
+                XMLStreamWriter.class}, new PrettyPrintHandler(
+                    xmlFactory.createXMLStreamWriter(w)));
+
+            xml.writeStartDocument();
+            xmlConsumer.accept(xml);
+            xml.writeEndDocument();
+            xml.flush();
+            xml.close();
+        } catch (XMLStreamException ex) {
+            throw new IOException(ex);
+        } catch (IOException ex) {
+            throw ex;
+        }
+    }
+
+    private static class PrettyPrintHandler implements InvocationHandler {
+
+        PrettyPrintHandler(XMLStreamWriter target) {
+            this.target = target;
+        }
+
+        @Override
+        public Object invoke(Object proxy, Method method, Object[] args) throws
+                Throwable {
+            switch (method.getName()) {
+                case "writeStartElement":
+                    // update state of parent node
+                    if (depth > 0) {
+                        hasChildElement.put(depth - 1, true);
+                    }
+                    // reset state of current node
+                    hasChildElement.put(depth, false);
+                    // indent for current depth
+                    target.writeCharacters(EOL);
+                    target.writeCharacters(repeat(depth, INDENT));
+                    depth++;
+                    break;
+                case "writeEndElement":
+                    depth--;
+                    if (hasChildElement.get(depth) == true) {
+                        target.writeCharacters(EOL);
+                        target.writeCharacters(repeat(depth, INDENT));
+                    }
+                    break;
+                case "writeProcessingInstruction":
+                case "writeEmptyElement":
+                    // update state of parent node
+                    if (depth > 0) {
+                        hasChildElement.put(depth - 1, true);
+                    }
+                    // indent for current depth
+                    target.writeCharacters(EOL);
+                    target.writeCharacters(repeat(depth, INDENT));
+                    break;
+                default:
+                    break;
+            }
+            method.invoke(target, args);
+            return null;
+        }
+
+        private static String repeat(int d, String s) {
+            StringBuilder sb = new StringBuilder();
+            while (d-- > 0) {
+                sb.append(s);
+            }
+            return sb.toString();
+        }
+
+        private final XMLStreamWriter target;
+        private int depth = 0;
+        private final Map<Integer, Boolean> hasChildElement = new HashMap<>();
+        private static final String INDENT = "  ";
+        private static final String EOL = "\n";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/JLinkBundlerHelper.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2015, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.Optional;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.regex.Matcher;
+import java.util.spi.ToolProvider;
+import java.util.jar.JarFile;
+import java.lang.module.Configuration;
+import java.lang.module.ResolvedModule;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import jdk.internal.module.ModulePath;
+
+
+final class JLinkBundlerHelper {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MainResources");
+
+    static final ToolProvider JLINK_TOOL =
+            ToolProvider.findFirst("jlink").orElseThrow();
+
+    static File getMainJar(Map<String, ? super Object> params) {
+        File result = null;
+        RelativeFileSet fileset =
+                StandardBundlerParam.MAIN_JAR.fetchFrom(params);
+
+        if (fileset != null) {
+            String filename = fileset.getIncludedFiles().iterator().next();
+            result = fileset.getBaseDirectory().toPath().
+                    resolve(filename).toFile();
+
+            if (result == null || !result.exists()) {
+                String srcdir =
+                    StandardBundlerParam.SOURCE_DIR.fetchFrom(params);
+
+                if (srcdir != null) {
+                    result = new File(srcdir + File.separator + filename);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    static String getMainClassFromModule(Map<String, ? super Object> params) {
+        String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
+        if (mainModule != null)  {
+
+            int index = mainModule.indexOf("/");
+            if (index > 0) {
+                return mainModule.substring(index + 1);
+            } else {
+                ModuleDescriptor descriptor =
+                        JLinkBundlerHelper.getMainModuleDescription(params);
+                if (descriptor != null) {
+                    Optional<String> mainClass = descriptor.mainClass();
+                    if (mainClass.isPresent()) {
+                        Log.verbose(MessageFormat.format(I18N.getString(
+                                    "message.module-class"),
+                                    mainClass.get(),
+                                    JLinkBundlerHelper.getMainModule(params)));
+                        return mainClass.get();
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    static String getMainModule(Map<String, ? super Object> params) {
+        String result = null;
+        String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
+
+        if (mainModule != null) {
+            int index = mainModule.indexOf("/");
+
+            if (index > 0) {
+                result = mainModule.substring(0, index);
+            } else {
+                result = mainModule;
+            }
+        }
+
+        return result;
+    }
+
+    static void execute(Map<String, ? super Object> params,
+            AbstractAppImageBuilder imageBuilder)
+            throws IOException, Exception {
+
+        List<Path> modulePath =
+                StandardBundlerParam.MODULE_PATH.fetchFrom(params);
+        Set<String> addModules =
+                StandardBundlerParam.ADD_MODULES.fetchFrom(params);
+        Set<String> limitModules =
+                StandardBundlerParam.LIMIT_MODULES.fetchFrom(params);
+        Path outputDir = imageBuilder.getRuntimeRoot();
+        File mainJar = getMainJar(params);
+        ModFile.ModType mainJarType = ModFile.ModType.Unknown;
+
+        if (mainJar != null) {
+            mainJarType = new ModFile(mainJar).getModType();
+        } else if (StandardBundlerParam.MODULE.fetchFrom(params) == null) {
+            // user specified only main class, all jars will be on the classpath
+            mainJarType = ModFile.ModType.UnnamedJar;
+        }
+
+        boolean bindServices =
+                StandardBundlerParam.BIND_SERVICES.fetchFrom(params);
+
+        // Modules
+        String mainModule = getMainModule(params);
+        if (mainModule == null) {
+            if (mainJarType == ModFile.ModType.UnnamedJar) {
+                if (addModules.isEmpty()) {
+                    // The default for an unnamed jar is ALL_DEFAULT
+                    addModules.add(ModuleHelper.ALL_DEFAULT);
+                }
+            } else if (mainJarType == ModFile.ModType.Unknown ||
+                    mainJarType == ModFile.ModType.ModularJar) {
+                addModules.add(ModuleHelper.ALL_DEFAULT);
+            }
+        }
+
+        Set<String> modules = new ModuleHelper(
+                modulePath, addModules, limitModules).modules();
+
+        if (mainModule != null) {
+            modules.add(mainModule);
+        }
+
+        runJLink(outputDir, modulePath, modules, limitModules,
+                new HashMap<String,String>(), bindServices);
+
+        imageBuilder.prepareApplicationFiles(params);
+    }
+
+
+    // Returns the path to the JDK modules in the user defined module path.
+    static Path findPathOfModule( List<Path> modulePath, String moduleName) {
+
+        for (Path path : modulePath) {
+            Path moduleNamePath = path.resolve(moduleName);
+
+            if (Files.exists(moduleNamePath)) {
+                return path;
+            }
+        }
+
+        return null;
+    }
+
+    static ModuleDescriptor getMainModuleDescription(Map<String, ? super Object> params) {
+        boolean hasModule = params.containsKey(StandardBundlerParam.MODULE.getID());
+        if (hasModule) {
+            List<Path> modulePath = StandardBundlerParam.MODULE_PATH.fetchFrom(params);
+            if (!modulePath.isEmpty()) {
+                ModuleFinder finder = ModuleFinder.of(modulePath.toArray(new Path[0]));
+                String mainModule = JLinkBundlerHelper.getMainModule(params);
+                Optional<ModuleReference> omref = finder.find(mainModule);
+                if (omref.isPresent()) {
+                    return omref.get().descriptor();
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /*
+     * Returns the set of modules that would be visible by default for
+     * a non-modular-aware application consisting of the given elements.
+     */
+    private static Set<String> getDefaultModules(
+            Collection<Path> paths, Collection<String> addModules) {
+
+        // the modules in the run-time image that export an API
+        Stream<String> systemRoots = ModuleFinder.ofSystem().findAll().stream()
+                .map(ModuleReference::descriptor)
+                .filter(JLinkBundlerHelper::exportsAPI)
+                .map(ModuleDescriptor::name);
+
+        Set<String> roots = Stream.concat(systemRoots,
+                 addModules.stream()).collect(Collectors.toSet());
+
+        ModuleFinder finder = createModuleFinder(paths);
+
+        return Configuration.empty()
+                .resolveAndBind(finder, ModuleFinder.of(), roots)
+                .modules()
+                .stream()
+                .map(ResolvedModule::name)
+                .collect(Collectors.toSet());
+    }
+
+    /*
+     * Returns true if the given module exports an API to all module.
+     */
+    private static boolean exportsAPI(ModuleDescriptor descriptor) {
+        return descriptor.exports()
+                .stream()
+                .anyMatch(e -> !e.isQualified());
+    }
+
+    private static ModuleFinder createModuleFinder(Collection<Path> modulePath) {
+        return ModuleFinder.compose(
+                ModulePath.of(JarFile.runtimeVersion(), true,
+                        modulePath.toArray(Path[]::new)),
+                ModuleFinder.ofSystem());
+    }
+
+    private static class ModuleHelper {
+        // The token for "all modules on the module path".
+        private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
+
+        // The token for "all valid runtime modules".
+        static final String ALL_DEFAULT = "ALL-DEFAULT";
+
+        private final Set<String> modules = new HashSet<>();
+        ModuleHelper(List<Path> paths, Set<String> addModules,
+                Set<String> limitModules) {
+            boolean addAllModulePath = false;
+            boolean addDefaultMods = false;
+
+            for (Iterator<String> iterator = addModules.iterator();
+                    iterator.hasNext();) {
+                String module = iterator.next();
+
+                switch (module) {
+                    case ALL_MODULE_PATH:
+                        iterator.remove();
+                        addAllModulePath = true;
+                        break;
+                    case ALL_DEFAULT:
+                        iterator.remove();
+                        addDefaultMods = true;
+                        break;
+                    default:
+                        this.modules.add(module);
+                }
+            }
+
+            if (addAllModulePath) {
+                this.modules.addAll(getModuleNamesFromPath(paths));
+            } else if (addDefaultMods) {
+                this.modules.addAll(getDefaultModules(
+                        paths, addModules));
+            }
+        }
+
+        Set<String> modules() {
+            return modules;
+        }
+
+        private static Set<String> getModuleNamesFromPath(List<Path> paths) {
+
+            return createModuleFinder(paths)
+                    .findAll()
+                    .stream()
+                    .map(ModuleReference::descriptor)
+                    .map(ModuleDescriptor::name)
+                    .collect(Collectors.toSet());
+        }
+    }
+
+    private static void runJLink(Path output, List<Path> modulePath,
+            Set<String> modules, Set<String> limitModules,
+            HashMap<String, String> user, boolean bindServices)
+            throws PackagerException {
+
+        // This is just to ensure jlink is given a non-existant directory
+        // The passed in output path should be non-existant or empty directory
+        try {
+            IOUtils.deleteRecursive(output.toFile());
+        } catch (IOException ioe) {
+            throw new PackagerException(ioe);
+        }
+
+        ArrayList<String> args = new ArrayList<String>();
+        args.add("--output");
+        args.add(output.toString());
+        if (modulePath != null && !modulePath.isEmpty()) {
+            args.add("--module-path");
+            args.add(getPathList(modulePath));
+        }
+        if (modules != null && !modules.isEmpty()) {
+            args.add("--add-modules");
+            args.add(getStringList(modules));
+        }
+        if (limitModules != null && !limitModules.isEmpty()) {
+            args.add("--limit-modules");
+            args.add(getStringList(limitModules));
+        }
+        if (user != null && !user.isEmpty()) {
+            for (Map.Entry<String, String> entry : user.entrySet()) {
+                args.add(entry.getKey());
+                args.add(entry.getValue());
+            }
+        } else {
+            args.add("--strip-native-commands");
+            args.add("--strip-debug");
+            args.add("--no-man-pages");
+            args.add("--no-header-files");
+            if (bindServices) {
+                args.add("--bind-services");
+            }
+        }
+
+        StringWriter writer = new StringWriter();
+        PrintWriter pw = new PrintWriter(writer);
+
+        Log.verbose("jlink arguments: " + args);
+        int retVal = JLINK_TOOL.run(pw, pw, args.toArray(new String[0]));
+        String jlinkOut = writer.toString();
+
+        if (retVal != 0) {
+            throw new PackagerException("error.jlink.failed" , jlinkOut);
+        } else if (jlinkOut.length() > 0) {
+            Log.verbose("jlink output: " + jlinkOut);
+        }
+    }
+
+    private static String getPathList(List<Path> pathList) {
+        String ret = null;
+        for (Path p : pathList) {
+            String s =  Matcher.quoteReplacement(p.toString());
+            if (ret == null) {
+                ret = s;
+            } else {
+                ret += File.pathSeparator +  s;
+            }
+        }
+        return ret;
+    }
+
+    private static String getStringList(Set<String> strings) {
+        String ret = null;
+        for (String s : strings) {
+            if (ret == null) {
+                ret = s;
+            } else {
+                ret += "," + s;
+            }
+        }
+        return (ret == null) ? null : Matcher.quoteReplacement(ret);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/JPackageToolProvider.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, 2019, 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.incubator.jpackage.internal;
+
+import java.io.PrintWriter;
+import java.util.spi.ToolProvider;
+
+/**
+ * JPackageToolProvider
+ *
+ * This is the ToolProvider implementation exported
+ * to java.util.spi.ToolProvider and ultimately javax.tools.ToolProvider
+ */
+public class JPackageToolProvider implements ToolProvider {
+
+    public String name() {
+        return "jpackage";
+    }
+
+    public synchronized int run(
+            PrintWriter out, PrintWriter err, String... args) {
+        try {
+            return new jdk.incubator.jpackage.main.Main().execute(out, err, args);
+        } catch (RuntimeException re) {
+            Log.error(re.getMessage());
+            Log.verbose(re);
+            return 1;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Log.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2011, 2019, 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.incubator.jpackage.internal;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * Log
+ *
+ * General purpose logging mechanism.
+ */
+public class Log {
+    public static class Logger {
+        private boolean verbose = false;
+        private PrintWriter out = null;
+        private PrintWriter err = null;
+
+        // verbose defaults to true unless environment variable JPACKAGE_DEBUG
+        // is set to true.
+        // Then it is only set to true by using --verbose jpackage option
+
+        public Logger() {
+            verbose = ("true".equals(System.getenv("JPACKAGE_DEBUG")));
+        }
+
+        public void setVerbose() {
+            verbose = true;
+        }
+
+        public boolean isVerbose() {
+            return verbose;
+        }
+
+        public void setPrintWriter(PrintWriter out, PrintWriter err) {
+            this.out = out;
+            this.err = err;
+        }
+
+        public void flush() {
+            if (out != null) {
+                out.flush();
+            }
+
+            if (err != null) {
+                err.flush();
+            }
+        }
+
+        public void info(String msg) {
+            if (out != null) {
+                out.println(msg);
+            } else {
+                System.out.println(msg);
+            }
+        }
+
+        public void error(String msg) {
+            if (err != null) {
+                err.println(msg);
+            } else {
+                System.err.println(msg);
+            }
+        }
+
+        public void verbose(Throwable t) {
+            if (out != null && verbose) {
+                t.printStackTrace(out);
+            } else if (verbose) {
+                t.printStackTrace(System.out);
+            }
+        }
+
+        public void verbose(String msg) {
+            if (out != null && verbose) {
+                out.println(msg);
+            } else if (verbose) {
+                System.out.println(msg);
+            }
+        }
+    }
+
+    private static Logger delegate = null;
+
+    public static void setLogger(Logger logger) {
+        delegate = (logger != null) ? logger : new Logger();
+    }
+
+    public static void flush() {
+        if (delegate != null) {
+            delegate.flush();
+        }
+    }
+
+    public static void info(String msg) {
+        if (delegate != null) {
+           delegate.info(msg);
+        }
+    }
+
+    public static void error(String msg) {
+        if (delegate != null) {
+            delegate.error(msg);
+        }
+    }
+
+    public static void setVerbose() {
+        if (delegate != null) {
+            delegate.setVerbose();
+        }
+    }
+
+    public static boolean isVerbose() {
+        return (delegate != null) ? delegate.isVerbose() : false;
+    }
+
+    public static void verbose(String msg) {
+        if (delegate != null) {
+           delegate.verbose(msg);
+        }
+    }
+
+    public static void verbose(Throwable t) {
+        if (delegate != null) {
+           delegate.verbose(t);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ModFile.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+final class ModFile {
+    private final String filename;
+    private final ModType moduleType;
+
+    enum JarType {All, UnnamedJar, ModularJar}
+    enum ModType {
+            Unknown, UnnamedJar, ModularJar, Jmod, ExplodedModule}
+
+    ModFile(File aFile) {
+        super();
+        filename = aFile.getPath();
+        moduleType = getModType(aFile);
+    }
+
+    String getModName() {
+        File file = new File(getFileName());
+        // do not try to remove extension for directories
+        return moduleType == ModType.ExplodedModule ?
+                file.getName() : getFileWithoutExtension(file.getName());
+    }
+
+    String getFileName() {
+        return filename;
+    }
+
+    ModType getModType() {
+        return moduleType;
+    }
+
+    private static ModType getModType(File aFile) {
+        ModType result = ModType.Unknown;
+        String filename = aFile.getAbsolutePath();
+
+        if (aFile.isFile()) {
+            if (filename.endsWith(".jmod")) {
+                result = ModType.Jmod;
+            }
+            else if (filename.endsWith(".jar")) {
+                JarType status = isModularJar(filename);
+
+                if (status == JarType.ModularJar) {
+                    result = ModType.ModularJar;
+                }
+                else if (status == JarType.UnnamedJar) {
+                    result = ModType.UnnamedJar;
+                }
+            }
+        }
+        else if (aFile.isDirectory()) {
+            File moduleInfo = new File(
+                    filename + File.separator + "module-info.class");
+
+            if (moduleInfo.exists()) {
+                result = ModType.ExplodedModule;
+            }
+        }
+
+        return result;
+    }
+
+    private static JarType isModularJar(String FileName) {
+        JarType result = JarType.All;
+
+        try (ZipInputStream zip =
+                    new ZipInputStream(new FileInputStream(FileName))) {
+            result = JarType.UnnamedJar;
+
+            for (ZipEntry entry = zip.getNextEntry(); entry != null;
+                    entry = zip.getNextEntry()) {
+                if (entry.getName().matches("module-info.class")) {
+                    result = JarType.ModularJar;
+                    break;
+                }
+            }
+        } catch (IOException ex) {
+        }
+
+        return result;
+    }
+
+    private static String getFileWithoutExtension(String FileName) {
+        return FileName.replaceFirst("[.][^.]+$", "");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/OverridableResource.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.RESOURCE_DIR;
+import jdk.incubator.jpackage.internal.resources.ResourceLocator;
+
+/**
+ * Resource file that may have the default value supplied by jpackage. It can be
+ * overridden by a file from resource directory set with {@code --resource-dir}
+ * jpackage parameter.
+ *
+ * Resource has default name and public name. Default name is the name of a file
+ * in {@code jdk.incubator.jpackage.internal.resources} package that provides the default
+ * value of the resource.
+ *
+ * Public name is a path relative to resource directory to a file with custom
+ * value of the resource.
+ *
+ * Use #setPublicName to set the public name.
+ *
+ * If #setPublicName was not called, name of file passed in #saveToFile function
+ * will be used as a public name.
+ *
+ * Use #setExternal to set arbitrary file as a source of resource. If non-null
+ * value was passed in #setExternal call that value will be used as a path to file
+ * to copy in the destination file passed in #saveToFile function call.
+ */
+final class OverridableResource {
+
+    OverridableResource(String defaultName) {
+        this.defaultName = defaultName;
+    }
+
+    OverridableResource setSubstitutionData(Map<String, String> v) {
+        if (v != null) {
+            // Disconnect `v`
+            substitutionData = new HashMap<>(v);
+        } else {
+            substitutionData = null;
+        }
+        return this;
+    }
+
+    OverridableResource setCategory(String v) {
+        category = v;
+        return this;
+    }
+
+    OverridableResource setResourceDir(Path v) {
+        resourceDir = v;
+        return this;
+    }
+
+    OverridableResource setResourceDir(File v) {
+        return setResourceDir(toPath(v));
+    }
+
+    /**
+     * Set name of file to look for in resource dir.
+     *
+     * @return this
+     */
+    OverridableResource setPublicName(Path v) {
+        publicName = v;
+        return this;
+    }
+
+    OverridableResource setPublicName(String v) {
+        return setPublicName(Path.of(v));
+    }
+
+    OverridableResource setExternal(Path v) {
+        externalPath = v;
+        return this;
+    }
+
+    OverridableResource setExternal(File v) {
+        return setExternal(toPath(v));
+    }
+
+    void saveToFile(Path dest) throws IOException {
+        final String printableCategory;
+        if (category != null) {
+            printableCategory = String.format("[%s]", category);
+        } else {
+            printableCategory = "";
+        }
+
+        if (externalPath != null && externalPath.toFile().exists()) {
+            Log.verbose(MessageFormat.format(I18N.getString(
+                    "message.using-custom-resource-from-file"),
+                    printableCategory,
+                    externalPath.toAbsolutePath().normalize()));
+
+            try (InputStream in = Files.newInputStream(externalPath)) {
+                processResourceStream(in, dest);
+            }
+            return;
+        }
+
+        final Path resourceName = Optional.ofNullable(publicName).orElse(
+                dest.getFileName());
+
+        if (resourceDir != null) {
+            final Path customResource = resourceDir.resolve(resourceName);
+            if (customResource.toFile().exists()) {
+                Log.verbose(MessageFormat.format(I18N.getString(
+                        "message.using-custom-resource"), printableCategory,
+                        resourceDir.normalize().toAbsolutePath().relativize(
+                                customResource.normalize().toAbsolutePath())));
+
+                try (InputStream in = Files.newInputStream(customResource)) {
+                    processResourceStream(in, dest);
+                }
+                return;
+            }
+        }
+
+        if (defaultName != null) {
+            Log.verbose(MessageFormat.format(
+                    I18N.getString("message.using-default-resource"),
+                    defaultName, printableCategory, resourceName));
+
+            try (InputStream in = readDefault(defaultName)) {
+                processResourceStream(in, dest);
+            }
+        }
+    }
+
+    void saveToFile(File dest) throws IOException {
+        saveToFile(dest.toPath());
+    }
+
+    static InputStream readDefault(String resourceName) {
+        return ResourceLocator.class.getResourceAsStream(resourceName);
+    }
+
+    static OverridableResource createResource(String defaultName,
+            Map<String, ? super Object> params) {
+        return new OverridableResource(defaultName).setResourceDir(
+                RESOURCE_DIR.fetchFrom(params));
+    }
+
+    private static List<String> substitute(Stream<String> lines,
+            Map<String, String> substitutionData) {
+        return lines.map(line -> {
+            String result = line;
+            for (var entry : substitutionData.entrySet()) {
+                result = result.replace(entry.getKey(), Optional.ofNullable(
+                        entry.getValue()).orElse(""));
+            }
+            return result;
+        }).collect(Collectors.toList());
+    }
+
+    private static Path toPath(File v) {
+        if (v != null) {
+            return v.toPath();
+        }
+        return null;
+    }
+
+    private void processResourceStream(InputStream rawResource, Path dest)
+            throws IOException {
+        if (substitutionData == null) {
+            Files.createDirectories(dest.getParent());
+            Files.copy(rawResource, dest, StandardCopyOption.REPLACE_EXISTING);
+        } else {
+            // Utf8 in and out
+            try (BufferedReader reader = new BufferedReader(
+                    new InputStreamReader(rawResource, StandardCharsets.UTF_8))) {
+                Files.createDirectories(dest.getParent());
+                Files.write(dest, substitute(reader.lines(), substitutionData));
+            }
+        }
+    }
+
+    private Map<String, String> substitutionData;
+    private String category;
+    private Path resourceDir;
+    private Path publicName;
+    private Path externalPath;
+    private final String defaultName;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/PackagerException.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011, 2019, 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.incubator.jpackage.internal;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+public class PackagerException extends Exception {
+    private static final long serialVersionUID = 1L;
+    private static final ResourceBundle bundle = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MainResources");
+
+    public PackagerException(Throwable cause) {
+        super(cause);
+    }
+
+    public PackagerException(String key, Throwable cause) {
+        super(bundle.getString(key), cause);
+    }
+
+    public PackagerException(String key) {
+        super(bundle.getString(key));
+    }
+
+    public PackagerException(String key, String ... arguments) {
+        super(MessageFormat.format(
+                bundle.getString(key), (Object[]) arguments));
+    }
+
+    public PackagerException(
+            Throwable cause, String key, String ... arguments) {
+        super(MessageFormat.format(bundle.getString(key),
+                (Object[]) arguments), cause);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/PathGroup.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+
+/**
+ * Group of paths.
+ * Each path in the group is assigned a unique id.
+ */
+final class PathGroup {
+    PathGroup(Map<Object, Path> paths) {
+        entries = new HashMap<>(paths);
+    }
+
+    Path getPath(Object id) {
+        if (id == null) {
+            throw new NullPointerException();
+        }
+        return entries.get(id);
+    }
+
+    void setPath(Object id, Path path) {
+        if (path != null) {
+            entries.put(id, path);
+        } else {
+            entries.remove(id);
+        }
+    }
+
+    /**
+     * All configured entries.
+     */
+    List<Path> paths() {
+        return entries.values().stream().collect(Collectors.toList());
+    }
+
+    /**
+     * Root entries.
+     */
+    List<Path> roots() {
+        // Sort by the number of path components in ascending order.
+        List<Map.Entry<Path, Path>> sorted = normalizedPaths().stream().sorted(
+                (a, b) -> a.getKey().getNameCount() - b.getKey().getNameCount()).collect(
+                        Collectors.toList());
+
+        // Returns `true` if `a` is a parent of `b`
+        BiFunction<Map.Entry<Path, Path>, Map.Entry<Path, Path>, Boolean> isParentOrSelf = (a, b) -> {
+            return a == b || b.getKey().startsWith(a.getKey());
+        };
+
+        return sorted.stream().filter(
+                v -> v == sorted.stream().sequential().filter(
+                        v2 -> isParentOrSelf.apply(v2, v)).findFirst().get()).map(
+                        v -> v.getValue()).collect(Collectors.toList());
+    }
+
+    long sizeInBytes() throws IOException {
+        long reply = 0;
+        for (Path dir : roots().stream().filter(f -> Files.isDirectory(f)).collect(
+                Collectors.toList())) {
+            try (Stream<Path> stream = Files.walk(dir)) {
+                reply += stream.filter(p -> Files.isRegularFile(p)).mapToLong(
+                        f -> f.toFile().length()).sum();
+            }
+        }
+        return reply;
+    }
+
+    PathGroup resolveAt(Path root) {
+        return new PathGroup(entries.entrySet().stream().collect(
+                Collectors.toMap(e -> e.getKey(),
+                        e -> root.resolve(e.getValue()))));
+    }
+
+    void copy(PathGroup dst) throws IOException {
+        copy(this, dst, null, false);
+    }
+
+    void move(PathGroup dst) throws IOException {
+        copy(this, dst, null, true);
+    }
+
+    void transform(PathGroup dst, TransformHandler handler) throws IOException {
+        copy(this, dst, handler, false);
+    }
+
+    static interface Facade<T> {
+        PathGroup pathGroup();
+
+        default Collection<Path> paths() {
+            return pathGroup().paths();
+        }
+
+        default List<Path> roots() {
+            return pathGroup().roots();
+        }
+
+        default long sizeInBytes() throws IOException {
+            return pathGroup().sizeInBytes();
+        }
+
+        T resolveAt(Path root);
+
+        default void copy(Facade<T> dst) throws IOException {
+            pathGroup().copy(dst.pathGroup());
+        }
+
+        default void move(Facade<T> dst) throws IOException {
+            pathGroup().move(dst.pathGroup());
+        }
+
+        default void transform(Facade<T> dst, TransformHandler handler) throws
+                IOException {
+            pathGroup().transform(dst.pathGroup(), handler);
+        }
+    }
+
+    static interface TransformHandler {
+        public void copyFile(Path src, Path dst) throws IOException;
+        public void createDirectory(Path dir) throws IOException;
+    }
+
+    private static void copy(PathGroup src, PathGroup dst,
+            TransformHandler handler, boolean move) throws IOException {
+        List<Map.Entry<Path, Path>> copyItems = new ArrayList<>();
+        List<Path> excludeItems = new ArrayList<>();
+
+        for (var id: src.entries.keySet()) {
+            Path srcPath = src.entries.get(id);
+            if (dst.entries.containsKey(id)) {
+                copyItems.add(Map.entry(srcPath, dst.entries.get(id)));
+            } else {
+                excludeItems.add(srcPath);
+            }
+        }
+
+        copy(move, copyItems, excludeItems, handler);
+    }
+
+    private static void copy(boolean move, List<Map.Entry<Path, Path>> entries,
+            List<Path> excludePaths, TransformHandler handler) throws
+            IOException {
+
+        if (handler == null) {
+            handler = new TransformHandler() {
+                @Override
+                public void copyFile(Path src, Path dst) throws IOException {
+                    Files.createDirectories(dst.getParent());
+                    if (move) {
+                        Files.move(src, dst);
+                    } else {
+                        Files.copy(src, dst);
+                    }
+                }
+
+                @Override
+                public void createDirectory(Path dir) throws IOException {
+                    Files.createDirectories(dir);
+                }
+            };
+        }
+
+        // destination -> source file mapping
+        Map<Path, Path> actions = new HashMap<>();
+        for (var action: entries) {
+            Path src = action.getKey();
+            Path dst = action.getValue();
+            if (src.toFile().isDirectory()) {
+               try (Stream<Path> stream = Files.walk(src)) {
+                   stream.sequential().forEach(path -> actions.put(dst.resolve(
+                            src.relativize(path)).normalize(), path));
+               }
+            } else {
+                actions.put(dst.normalize(), src);
+            }
+        }
+
+        for (var action : actions.entrySet()) {
+            Path dst = action.getKey();
+            Path src = action.getValue();
+
+            if (excludePaths.stream().anyMatch(src::startsWith)) {
+                continue;
+            }
+
+            if (src.equals(dst) || !src.toFile().exists()) {
+                continue;
+            }
+
+            if (src.toFile().isDirectory()) {
+                handler.createDirectory(dst);
+            } else {
+                handler.copyFile(src, dst);
+            }
+        }
+
+        if (move) {
+            // Delete source dirs.
+            for (var entry: entries) {
+                File srcFile = entry.getKey().toFile();
+                if (srcFile.isDirectory()) {
+                    IOUtils.deleteRecursive(srcFile);
+                }
+            }
+        }
+    }
+
+    private static Map.Entry<Path, Path> normalizedPath(Path v) {
+        final Path normalized;
+        if (!v.isAbsolute()) {
+            normalized = Path.of("./").resolve(v.normalize());
+        } else {
+            normalized = v.normalize();
+        }
+
+        return Map.entry(normalized, v);
+    }
+
+    private List<Map.Entry<Path, Path>> normalizedPaths() {
+        return entries.values().stream().map(PathGroup::normalizedPath).collect(
+                Collectors.toList());
+    }
+
+    private final Map<Object, Path> entries;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Platform.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2016, 2019, 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.incubator.jpackage.internal;
+
+import java.util.regex.Pattern;
+
+/**
+ * Platform
+ *
+ * Use <code>Platform</code> to detect the operating system
+ * that is currently running.
+ *
+ * Example:
+ *
+ *  Platform platform = Platform.getPlatform();
+ *
+ *  switch(platform) {
+ *    case Platform.MAC: {
+ *      // Do something
+ *      break;
+ *    }
+ *    case Platform.WINDOWS:
+ *    case Platform.LINUX: {
+ *      // Do something else
+ *    }
+ *  }
+ *
+ */
+enum Platform {UNKNOWN, WINDOWS, LINUX, MAC;
+    private static final Platform platform;
+    private static final int majorVersion;
+    private static final int minorVersion;
+
+    static {
+        String os = System.getProperty("os.name").toLowerCase();
+
+        if (os.indexOf("win") >= 0) {
+            platform = Platform.WINDOWS;
+        }
+        else if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) {
+            platform = Platform.LINUX;
+        }
+        else if (os.indexOf("mac") >= 0) {
+            platform = Platform.MAC;
+        }
+        else {
+            platform = Platform.UNKNOWN;
+        }
+
+        String version = System.getProperty("os.version").toString();
+        String[] parts = version.split(Pattern.quote("."));
+
+        if (parts.length > 0) {
+            majorVersion = Integer.parseInt(parts[0]);
+
+            if (parts.length > 1) {
+                minorVersion = Integer.parseInt(parts[1]);
+            }
+            else {
+                minorVersion = -1;
+            }
+        }
+        else {
+            majorVersion = -1;
+            minorVersion = -1;
+        }
+    }
+
+    private Platform() {}
+
+    static Platform getPlatform() {
+        return platform;
+    }
+
+    static int getMajorVersion() {
+        return majorVersion;
+    }
+
+    static int getMinorVersion() {
+        return minorVersion;
+    }
+
+    static boolean isWindows() {
+        return getPlatform() == WINDOWS;
+    }
+
+    static boolean isMac() {
+        return getPlatform() == MAC;
+    }
+
+    static boolean isLinux() {
+        return getPlatform() == LINUX;
+    }
+
+    static RuntimeException throwUnknownPlatformError() {
+        throw new IllegalArgumentException("Unknown platform");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/PlatformPackage.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.nio.file.Path;
+
+/**
+ *
+ * Platform package of an application.
+ */
+interface PlatformPackage {
+    /**
+     * Platform-specific package name.
+     */
+    String name();
+
+    /**
+     * Root directory where sources for packaging tool should be stored
+     */
+    Path sourceRoot();
+
+    /**
+     * Source application layout from which to build the package.
+     */
+    ApplicationLayout sourceApplicationLayout();
+
+    /**
+     * Application layout of the installed package.
+     */
+    ApplicationLayout installedApplicationLayout();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/RelativeFileSet.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * RelativeFileSet
+ *
+ * A class encapsulating a directory and a set of files within it.
+ */
+class RelativeFileSet {
+
+    private File basedir;
+    private Set<String> files = new LinkedHashSet<>();
+
+    RelativeFileSet(File base, Collection<File> files) {
+        basedir = base;
+        String baseAbsolute = basedir.getAbsolutePath();
+        for (File f: files) {
+            String absolute = f.getAbsolutePath();
+            if (!absolute.startsWith(baseAbsolute)) {
+                throw new RuntimeException("File " + f.getAbsolutePath() +
+                        " does not belong to " + baseAbsolute);
+            }
+            if (!absolute.equals(baseAbsolute)) {
+                    // possible in jpackage case
+                this.files.add(absolute.substring(baseAbsolute.length()+1));
+            }
+        }
+    }
+
+    RelativeFileSet(File base, Set<File> files) {
+        this(base, (Collection<File>) files);
+    }
+
+    File getBaseDirectory() {
+        return basedir;
+    }
+
+    Set<String> getIncludedFiles() {
+        return files;
+    }
+
+    @Override
+    public String toString() {
+        if (files.size() ==  1) {
+            return "" + basedir + File.pathSeparator + files;
+        }
+        return "RelativeFileSet {basedir:" + basedir
+                + ", files: {" + files + "}";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ScriptRunner.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME;
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
+
+/**
+ * Runs custom script from resource directory.
+ */
+class ScriptRunner {
+    ScriptRunner() {
+        environment = new ProcessBuilder().environment();
+    }
+
+    ScriptRunner setResourceCategoryId(String v) {
+        resourceCategoryId = v;
+        return this;
+    }
+
+    ScriptRunner setDirectory(Path v) {
+        directory = v;
+        return this;
+    }
+
+    ScriptRunner setScriptNameSuffix(String v) {
+        scriptNameSuffix = v;
+        return this;
+    }
+
+    ScriptRunner addEnvironment(Map<String, String> v) {
+        environment.putAll(v);
+        return this;
+    }
+
+    ScriptRunner setEnvironmentVariable(String envVarName, String envVarValue) {
+        Objects.requireNonNull(envVarName);
+        if (envVarValue == null) {
+            environment.remove(envVarName);
+        } else {
+            environment.put(envVarName, envVarValue);
+        }
+        return this;
+    }
+
+    public void run(Map<String, ? super Object> params) throws IOException {
+        String scriptName = String.format("%s-%s%s", APP_NAME.fetchFrom(params),
+                scriptNameSuffix, scriptSuffix());
+        Path scriptPath = CONFIG_ROOT.fetchFrom(params).toPath().resolve(
+                scriptName);
+        createResource(null, params)
+                .setCategory(I18N.getString(resourceCategoryId))
+                .saveToFile(scriptPath);
+        if (!Files.exists(scriptPath)) {
+            return;
+        }
+
+        ProcessBuilder pb = new ProcessBuilder(shell(),
+                scriptPath.toAbsolutePath().toString());
+        Map<String, String> workEnvironment = pb.environment();
+        workEnvironment.clear();
+        workEnvironment.putAll(environment);
+
+        if (directory != null) {
+            pb.directory(directory.toFile());
+        }
+
+        Executor.of(pb).executeExpectSuccess();
+    }
+
+    private static String shell() {
+        if (Platform.isWindows()) {
+            return "cscript";
+        }
+        return Optional.ofNullable(System.getenv("SHELL")).orElseGet(() -> "sh");
+    }
+
+    private static String scriptSuffix() {
+        if (Platform.isWindows()) {
+            return ".wsf";
+        }
+        return ".sh";
+    }
+
+    private String scriptNameSuffix;
+    private String resourceCategoryId;
+    private Path directory;
+    private Map<String, String> environment;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/StandardBundlerParam.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,790 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Version;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * StandardBundlerParam
+ *
+ * A parameter to a bundler.
+ *
+ * Also contains static definitions of all of the common bundler parameters.
+ * (additional platform specific and mode specific bundler parameters
+ * are defined in each of the specific bundlers)
+ *
+ * Also contains static methods that operate on maps of parameters.
+ */
+class StandardBundlerParam<T> extends BundlerParamInfo<T> {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MainResources");
+    private static final String JAVABASEJMOD = "java.base.jmod";
+    private final static String DEFAULT_VERSION = "1.0";
+    private final static String DEFAULT_RELEASE = "1";
+
+    StandardBundlerParam(String id, Class<T> valueType,
+            Function<Map<String, ? super Object>, T> defaultValueFunction,
+            BiFunction<String, Map<String, ? super Object>, T> stringConverter)
+    {
+        this.id = id;
+        this.valueType = valueType;
+        this.defaultValueFunction = defaultValueFunction;
+        this.stringConverter = stringConverter;
+    }
+
+    static final StandardBundlerParam<RelativeFileSet> APP_RESOURCES =
+            new StandardBundlerParam<>(
+                    BundleParams.PARAM_APP_RESOURCES,
+                    RelativeFileSet.class,
+                    null, // no default.  Required parameter
+                    null  // no string translation,
+                          // tool must provide complex type
+            );
+
+    @SuppressWarnings("unchecked")
+    static final
+            StandardBundlerParam<List<RelativeFileSet>> APP_RESOURCES_LIST =
+            new StandardBundlerParam<>(
+                    BundleParams.PARAM_APP_RESOURCES + "List",
+                    (Class<List<RelativeFileSet>>) (Object) List.class,
+                    // Default is appResources, as a single item list
+                    p -> new ArrayList<>(Collections.singletonList(
+                            APP_RESOURCES.fetchFrom(p))),
+                    StandardBundlerParam::createAppResourcesListFromString
+            );
+
+    static final StandardBundlerParam<String> SOURCE_DIR =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.INPUT.getId(),
+                    String.class,
+                    p -> null,
+                    (s, p) -> {
+                        String value = String.valueOf(s);
+                        if (value.charAt(value.length() - 1) ==
+                                File.separatorChar) {
+                            return value.substring(0, value.length() - 1);
+                        }
+                        else {
+                            return value;
+                        }
+                    }
+            );
+
+    // note that each bundler is likely to replace this one with
+    // their own converter
+    static final StandardBundlerParam<RelativeFileSet> MAIN_JAR =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.MAIN_JAR.getId(),
+                    RelativeFileSet.class,
+                    params -> {
+                        extractMainClassInfoFromAppResources(params);
+                        return (RelativeFileSet) params.get("mainJar");
+                    },
+                    (s, p) -> getMainJar(s, p)
+            );
+
+    static final StandardBundlerParam<String> CLASSPATH =
+            new StandardBundlerParam<>(
+                    "classpath",
+                    String.class,
+                    params -> {
+                        extractMainClassInfoFromAppResources(params);
+                        String cp = (String) params.get("classpath");
+                        return cp == null ? "" : cp;
+                    },
+                    (s, p) -> s
+            );
+
+    static final StandardBundlerParam<String> MAIN_CLASS =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.APPCLASS.getId(),
+                    String.class,
+                    params -> {
+                        if (isRuntimeInstaller(params)) {
+                            return null;
+                        }
+                        extractMainClassInfoFromAppResources(params);
+                        String s = (String) params.get(
+                                BundleParams.PARAM_APPLICATION_CLASS);
+                        if (s == null) {
+                            s = JLinkBundlerHelper.getMainClassFromModule(
+                                    params);
+                        }
+                        return s;
+                    },
+                    (s, p) -> s
+            );
+
+    static final StandardBundlerParam<File> PREDEFINED_RUNTIME_IMAGE =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId(),
+                    File.class,
+                    params -> null,
+                    (s, p) -> new File(s)
+            );
+
+    static final StandardBundlerParam<String> APP_NAME =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.NAME.getId(),
+                    String.class,
+                    params -> {
+                        String s = MAIN_CLASS.fetchFrom(params);
+                        if (s != null) {
+                            int idx = s.lastIndexOf(".");
+                            if (idx >= 0) {
+                                return s.substring(idx+1);
+                            }
+                            return s;
+                        } else if (isRuntimeInstaller(params)) {
+                            File f = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
+                            if (f != null) {
+                                return f.getName();
+                            }
+                        }
+                        return null;
+                    },
+                    (s, p) -> s
+            );
+
+    static final StandardBundlerParam<File> ICON =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.ICON.getId(),
+                    File.class,
+                    params -> null,
+                    (s, p) -> new File(s)
+            );
+
+    static final StandardBundlerParam<String> VENDOR =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.VENDOR.getId(),
+                    String.class,
+                    params -> I18N.getString("param.vendor.default"),
+                    (s, p) -> s
+            );
+
+    static final StandardBundlerParam<String> DESCRIPTION =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.DESCRIPTION.getId(),
+                    String.class,
+                    params -> params.containsKey(APP_NAME.getID())
+                            ? APP_NAME.fetchFrom(params)
+                            : I18N.getString("param.description.default"),
+                    (s, p) -> s
+            );
+
+    static final StandardBundlerParam<String> COPYRIGHT =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.COPYRIGHT.getId(),
+                    String.class,
+                    params -> MessageFormat.format(I18N.getString(
+                            "param.copyright.default"), new Date()),
+                    (s, p) -> s
+            );
+
+    @SuppressWarnings("unchecked")
+    static final StandardBundlerParam<List<String>> ARGUMENTS =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.ARGUMENTS.getId(),
+                    (Class<List<String>>) (Object) List.class,
+                    params -> Collections.emptyList(),
+                    (s, p) -> null
+            );
+
+    @SuppressWarnings("unchecked")
+    static final StandardBundlerParam<List<String>> JAVA_OPTIONS =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.JAVA_OPTIONS.getId(),
+                    (Class<List<String>>) (Object) List.class,
+                    params -> Collections.emptyList(),
+                    (s, p) -> Arrays.asList(s.split("\n\n"))
+            );
+
+    // note that each bundler is likely to replace this one with
+    // their own converter
+    static final StandardBundlerParam<String> VERSION =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.VERSION.getId(),
+                    String.class,
+                    params -> getDefaultAppVersion(params),
+                    (s, p) -> s
+            );
+
+    static final StandardBundlerParam<String> RELEASE =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.RELEASE.getId(),
+                    String.class,
+                    params -> DEFAULT_RELEASE,
+                    (s, p) -> s
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final StandardBundlerParam<String> LICENSE_FILE =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.LICENSE_FILE.getId(),
+                    String.class,
+                    params -> null,
+                    (s, p) -> s
+            );
+
+    static final StandardBundlerParam<File> TEMP_ROOT =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.TEMP_ROOT.getId(),
+                    File.class,
+                    params -> {
+                        try {
+                            return Files.createTempDirectory(
+                                    "jdk.incubator.jpackage").toFile();
+                        } catch (IOException ioe) {
+                            return null;
+                        }
+                    },
+                    (s, p) -> new File(s)
+            );
+
+    public static final StandardBundlerParam<File> CONFIG_ROOT =
+            new StandardBundlerParam<>(
+                "configRoot",
+                File.class,
+                params -> {
+                    File root =
+                            new File(TEMP_ROOT.fetchFrom(params), "config");
+                    root.mkdirs();
+                    return root;
+                },
+                (s, p) -> null
+            );
+
+    static final StandardBundlerParam<String> IDENTIFIER =
+            new StandardBundlerParam<>(
+                    "identifier.default",
+                    String.class,
+                    params -> {
+                        String s = MAIN_CLASS.fetchFrom(params);
+                        if (s == null) return null;
+
+                        int idx = s.lastIndexOf(".");
+                        if (idx >= 1) {
+                            return s.substring(0, idx);
+                        }
+                        return s;
+                    },
+                    (s, p) -> s
+            );
+
+    static final StandardBundlerParam<Boolean> BIND_SERVICES =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.BIND_SERVICES.getId(),
+                    Boolean.class,
+                    params -> false,
+                    (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
+                            true : Boolean.valueOf(s)
+            );
+
+
+    static final StandardBundlerParam<Boolean> VERBOSE  =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.VERBOSE.getId(),
+                    Boolean.class,
+                    params -> false,
+                    // valueOf(null) is false, and we actually do want null
+                    (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
+                            true : Boolean.valueOf(s)
+            );
+
+    static final StandardBundlerParam<File> RESOURCE_DIR =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.RESOURCE_DIR.getId(),
+                    File.class,
+                    params -> null,
+                    (s, p) -> new File(s)
+            );
+
+    static final BundlerParamInfo<String> INSTALL_DIR =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.INSTALL_DIR.getId(),
+                    String.class,
+                     params -> null,
+                    (s, p) -> s
+    );
+
+    static final StandardBundlerParam<File> PREDEFINED_APP_IMAGE =
+            new StandardBundlerParam<>(
+            Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId(),
+            File.class,
+            params -> null,
+            (s, p) -> new File(s));
+
+    @SuppressWarnings("unchecked")
+    static final StandardBundlerParam<List<Map<String, ? super Object>>> ADD_LAUNCHERS =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.ADD_LAUNCHER.getId(),
+                    (Class<List<Map<String, ? super Object>>>) (Object)
+                            List.class,
+                    params -> new ArrayList<>(1),
+                    // valueOf(null) is false, and we actually do want null
+                    (s, p) -> null
+            );
+
+    @SuppressWarnings("unchecked")
+    static final StandardBundlerParam
+            <List<Map<String, ? super Object>>> FILE_ASSOCIATIONS =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.FILE_ASSOCIATIONS.getId(),
+                    (Class<List<Map<String, ? super Object>>>) (Object)
+                            List.class,
+                    params -> new ArrayList<>(1),
+                    // valueOf(null) is false, and we actually do want null
+                    (s, p) -> null
+            );
+
+    @SuppressWarnings("unchecked")
+    static final StandardBundlerParam<List<String>> FA_EXTENSIONS =
+            new StandardBundlerParam<>(
+                    "fileAssociation.extension",
+                    (Class<List<String>>) (Object) List.class,
+                    params -> null, // null means not matched to an extension
+                    (s, p) -> Arrays.asList(s.split("(,|\\s)+"))
+            );
+
+    @SuppressWarnings("unchecked")
+    static final StandardBundlerParam<List<String>> FA_CONTENT_TYPE =
+            new StandardBundlerParam<>(
+                    "fileAssociation.contentType",
+                    (Class<List<String>>) (Object) List.class,
+                    params -> null,
+                            // null means not matched to a content/mime type
+                    (s, p) -> Arrays.asList(s.split("(,|\\s)+"))
+            );
+
+    static final StandardBundlerParam<String> FA_DESCRIPTION =
+            new StandardBundlerParam<>(
+                    "fileAssociation.description",
+                    String.class,
+                    params -> APP_NAME.fetchFrom(params) + " File",
+                    null
+            );
+
+    static final StandardBundlerParam<File> FA_ICON =
+            new StandardBundlerParam<>(
+                    "fileAssociation.icon",
+                    File.class,
+                    ICON::fetchFrom,
+                    (s, p) -> new File(s)
+            );
+
+    @SuppressWarnings("unchecked")
+    static final BundlerParamInfo<List<Path>> MODULE_PATH =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.MODULE_PATH.getId(),
+                    (Class<List<Path>>) (Object)List.class,
+                    p -> { return getDefaultModulePath(); },
+                    (s, p) -> {
+                        List<Path> modulePath = Arrays.asList(s
+                                .split(File.pathSeparator)).stream()
+                                .map(ss -> new File(ss).toPath())
+                                .collect(Collectors.toList());
+                        Path javaBasePath = null;
+                        if (modulePath != null) {
+                            javaBasePath = JLinkBundlerHelper
+                                    .findPathOfModule(modulePath, JAVABASEJMOD);
+                        } else {
+                            modulePath = new ArrayList<Path>();
+                        }
+
+                        // Add the default JDK module path to the module path.
+                        if (javaBasePath == null) {
+                            List<Path> jdkModulePath = getDefaultModulePath();
+
+                            if (jdkModulePath != null) {
+                                modulePath.addAll(jdkModulePath);
+                                javaBasePath =
+                                        JLinkBundlerHelper.findPathOfModule(
+                                        modulePath, JAVABASEJMOD);
+                            }
+                        }
+
+                        if (javaBasePath == null ||
+                                !Files.exists(javaBasePath)) {
+                            Log.error(String.format(I18N.getString(
+                                    "warning.no.jdk.modules.found")));
+                        }
+
+                        return modulePath;
+                    });
+
+    static final BundlerParamInfo<String> MODULE =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.MODULE.getId(),
+                    String.class,
+                    p -> null,
+                    (s, p) -> {
+                        return String.valueOf(s);
+                    });
+
+    @SuppressWarnings("unchecked")
+    static final BundlerParamInfo<Set<String>> ADD_MODULES =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.ADD_MODULES.getId(),
+                    (Class<Set<String>>) (Object) Set.class,
+                    p -> new LinkedHashSet<String>(),
+                    (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(",")))
+            );
+
+    @SuppressWarnings("unchecked")
+    static final BundlerParamInfo<Set<String>> LIMIT_MODULES =
+            new StandardBundlerParam<>(
+                    "limit-modules",
+                    (Class<Set<String>>) (Object) Set.class,
+                    p -> new LinkedHashSet<String>(),
+                    (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(",")))
+            );
+
+    static boolean isRuntimeInstaller(Map<String, ? super Object> params) {
+        if (params.containsKey(MODULE.getID()) ||
+                params.containsKey(MAIN_JAR.getID()) ||
+                params.containsKey(PREDEFINED_APP_IMAGE.getID())) {
+            return false; // we are building or are given an application
+        }
+        // runtime installer requires --runtime-image, if this is false
+        // here then we should have thrown error validating args.
+        return params.containsKey(PREDEFINED_RUNTIME_IMAGE.getID());
+    }
+
+    static File getPredefinedAppImage(Map<String, ? super Object> params) {
+        File applicationImage = null;
+        if (PREDEFINED_APP_IMAGE.fetchFrom(params) != null) {
+            applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params);
+            if (!applicationImage.exists()) {
+                throw new RuntimeException(
+                        MessageFormat.format(I18N.getString(
+                                "message.app-image-dir-does-not-exist"),
+                                PREDEFINED_APP_IMAGE.getID(),
+                                applicationImage.toString()));
+            }
+        }
+        return applicationImage;
+    }
+
+    static void copyPredefinedRuntimeImage(
+            Map<String, ? super Object> params,
+            AbstractAppImageBuilder appBuilder)
+            throws IOException , ConfigException {
+        File topImage = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
+        if (!topImage.exists()) {
+            throw new ConfigException(
+                    MessageFormat.format(I18N.getString(
+                    "message.runtime-image-dir-does-not-exist"),
+                    PREDEFINED_RUNTIME_IMAGE.getID(),
+                    topImage.toString()),
+                    MessageFormat.format(I18N.getString(
+                    "message.runtime-image-dir-does-not-exist.advice"),
+                    PREDEFINED_RUNTIME_IMAGE.getID()));
+        }
+        File image = appBuilder.getRuntimeImageDir(topImage);
+        // copy whole runtime, need to skip jmods and src.zip
+        final List<String> excludes = Arrays.asList("jmods", "src.zip");
+        IOUtils.copyRecursive(image.toPath(), appBuilder.getRuntimeRoot(), excludes);
+
+        // if module-path given - copy modules to appDir/mods
+        List<Path> modulePath =
+                StandardBundlerParam.MODULE_PATH.fetchFrom(params);
+        List<Path> defaultModulePath = getDefaultModulePath();
+        Path dest = appBuilder.getAppModsDir();
+
+        if (dest != null) {
+            for (Path mp : modulePath) {
+                if (!defaultModulePath.contains(mp)) {
+                    Files.createDirectories(dest);
+                    IOUtils.copyRecursive(mp, dest);
+                }
+            }
+        }
+
+        appBuilder.prepareApplicationFiles(params);
+    }
+
+    static void extractMainClassInfoFromAppResources(
+            Map<String, ? super Object> params) {
+        boolean hasMainClass = params.containsKey(MAIN_CLASS.getID());
+        boolean hasMainJar = params.containsKey(MAIN_JAR.getID());
+        boolean hasMainJarClassPath = params.containsKey(CLASSPATH.getID());
+        boolean hasModule = params.containsKey(MODULE.getID());
+
+        if (hasMainClass && hasMainJar && hasMainJarClassPath || hasModule ||
+                isRuntimeInstaller(params)) {
+            return;
+        }
+
+        // it's a pair.
+        // The [0] is the srcdir [1] is the file relative to sourcedir
+        List<String[]> filesToCheck = new ArrayList<>();
+
+        if (hasMainJar) {
+            RelativeFileSet rfs = MAIN_JAR.fetchFrom(params);
+            for (String s : rfs.getIncludedFiles()) {
+                filesToCheck.add(
+                        new String[] {rfs.getBaseDirectory().toString(), s});
+            }
+        } else if (hasMainJarClassPath) {
+            for (String s : CLASSPATH.fetchFrom(params).split("\\s+")) {
+                if (APP_RESOURCES.fetchFrom(params) != null) {
+                    filesToCheck.add(
+                            new String[] {APP_RESOURCES.fetchFrom(params)
+                            .getBaseDirectory().toString(), s});
+                }
+            }
+        } else {
+            List<RelativeFileSet> rfsl = APP_RESOURCES_LIST.fetchFrom(params);
+            if (rfsl == null || rfsl.isEmpty()) {
+                return;
+            }
+            for (RelativeFileSet rfs : rfsl) {
+                if (rfs == null) continue;
+
+                for (String s : rfs.getIncludedFiles()) {
+                    filesToCheck.add(
+                            new String[]{rfs.getBaseDirectory().toString(), s});
+                }
+            }
+        }
+
+        // presume the set iterates in-order
+        for (String[] fnames : filesToCheck) {
+            try {
+                // only sniff jars
+                if (!fnames[1].toLowerCase().endsWith(".jar")) continue;
+
+                File file = new File(fnames[0], fnames[1]);
+                // that actually exist
+                if (!file.exists()) continue;
+
+                try (JarFile jf = new JarFile(file)) {
+                    Manifest m = jf.getManifest();
+                    Attributes attrs = (m != null) ?
+                            m.getMainAttributes() : null;
+
+                    if (attrs != null) {
+                        if (!hasMainJar) {
+                            if (fnames[0] == null) {
+                                fnames[0] = file.getParentFile().toString();
+                            }
+                            params.put(MAIN_JAR.getID(), new RelativeFileSet(
+                                    new File(fnames[0]),
+                                    new LinkedHashSet<>(Collections
+                                    .singletonList(file))));
+                        }
+                        if (!hasMainJarClassPath) {
+                            String cp =
+                                    attrs.getValue(Attributes.Name.CLASS_PATH);
+                            params.put(CLASSPATH.getID(),
+                                    cp == null ? "" : cp);
+                        }
+                        break;
+                    }
+                }
+            } catch (IOException ignore) {
+                ignore.printStackTrace();
+            }
+        }
+    }
+
+    static void validateMainClassInfoFromAppResources(
+            Map<String, ? super Object> params) throws ConfigException {
+        boolean hasMainClass = params.containsKey(MAIN_CLASS.getID());
+        boolean hasMainJar = params.containsKey(MAIN_JAR.getID());
+        boolean hasMainJarClassPath = params.containsKey(CLASSPATH.getID());
+        boolean hasModule = params.containsKey(MODULE.getID());
+        boolean hasAppImage = params.containsKey(PREDEFINED_APP_IMAGE.getID());
+
+        if (hasMainClass && hasMainJar && hasMainJarClassPath ||
+               hasAppImage || isRuntimeInstaller(params)) {
+            return;
+        }
+        if (hasModule) {
+            if (JLinkBundlerHelper.getMainClassFromModule(params) == null) {
+                throw new ConfigException(
+                        I18N.getString("ERR_NoMainClass"), null);
+            }
+        } else {
+            extractMainClassInfoFromAppResources(params);
+
+            if (!params.containsKey(MAIN_CLASS.getID())) {
+                if (hasMainJar) {
+                    throw new ConfigException(
+                            MessageFormat.format(I18N.getString(
+                            "error.no-main-class-with-main-jar"),
+                            MAIN_JAR.fetchFrom(params)),
+                            MessageFormat.format(I18N.getString(
+                            "error.no-main-class-with-main-jar.advice"),
+                            MAIN_JAR.fetchFrom(params)));
+                } else {
+                    throw new ConfigException(
+                            I18N.getString("error.no-main-class"),
+                            I18N.getString("error.no-main-class.advice"));
+                }
+            }
+        }
+    }
+
+    private static List<RelativeFileSet>
+            createAppResourcesListFromString(String s,
+            Map<String, ? super Object> objectObjectMap) {
+        List<RelativeFileSet> result = new ArrayList<>();
+        for (String path : s.split("[:;]")) {
+            File f = new File(path);
+            if (f.getName().equals("*") || path.endsWith("/") ||
+                    path.endsWith("\\")) {
+                if (f.getName().equals("*")) {
+                    f = f.getParentFile();
+                }
+                Set<File> theFiles = new HashSet<>();
+                try {
+                    try (Stream<Path> stream = Files.walk(f.toPath())) {
+                        stream.filter(Files::isRegularFile)
+                                .forEach(p -> theFiles.add(p.toFile()));
+                    }
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                result.add(new RelativeFileSet(f, theFiles));
+            } else {
+                result.add(new RelativeFileSet(f.getParentFile(),
+                        Collections.singleton(f)));
+            }
+        }
+        return result;
+    }
+
+    private static RelativeFileSet getMainJar(
+            String mainJarValue, Map<String, ? super Object> params) {
+        for (RelativeFileSet rfs : APP_RESOURCES_LIST.fetchFrom(params)) {
+            File appResourcesRoot = rfs.getBaseDirectory();
+            File mainJarFile = new File(appResourcesRoot, mainJarValue);
+
+            if (mainJarFile.exists()) {
+                return new RelativeFileSet(appResourcesRoot,
+                     new LinkedHashSet<>(Collections.singletonList(
+                     mainJarFile)));
+            }
+            mainJarFile = new File(mainJarValue);
+            if (mainJarFile.exists()) {
+                // absolute path for main-jar may fail is not legal
+                // below contains explicit error message.
+            } else {
+                List<Path> modulePath = MODULE_PATH.fetchFrom(params);
+                modulePath.removeAll(getDefaultModulePath());
+                if (!modulePath.isEmpty()) {
+                    Path modularJarPath = JLinkBundlerHelper.findPathOfModule(
+                            modulePath, mainJarValue);
+                    if (modularJarPath != null &&
+                            Files.exists(modularJarPath)) {
+                        return new RelativeFileSet(appResourcesRoot,
+                                new LinkedHashSet<>(Collections.singletonList(
+                                modularJarPath.toFile())));
+                    }
+                }
+            }
+        }
+
+        throw new IllegalArgumentException(
+                new ConfigException(MessageFormat.format(I18N.getString(
+                        "error.main-jar-does-not-exist"),
+                        mainJarValue), I18N.getString(
+                        "error.main-jar-does-not-exist.advice")));
+    }
+
+    static List<Path> getDefaultModulePath() {
+        List<Path> result = new ArrayList<Path>();
+        Path jdkModulePath = Paths.get(
+                System.getProperty("java.home"), "jmods").toAbsolutePath();
+
+        if (jdkModulePath != null && Files.exists(jdkModulePath)) {
+            result.add(jdkModulePath);
+        }
+        else {
+            // On a developer build the JDK Home isn't where we expect it
+            // relative to the jmods directory. Do some extra
+            // processing to find it.
+            Map<String, String> env = System.getenv();
+
+            if (env.containsKey("JDK_HOME")) {
+                jdkModulePath = Paths.get(env.get("JDK_HOME"),
+                        ".." + File.separator + "images"
+                        + File.separator + "jmods").toAbsolutePath();
+
+                if (jdkModulePath != null && Files.exists(jdkModulePath)) {
+                    result.add(jdkModulePath);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    static String getDefaultAppVersion(Map<String, ? super Object> params) {
+        String appVersion = DEFAULT_VERSION;
+
+        ModuleDescriptor descriptor = JLinkBundlerHelper.getMainModuleDescription(params);
+        if (descriptor != null) {
+            Optional<Version> oversion = descriptor.version();
+            if (oversion.isPresent()) {
+                Log.verbose(MessageFormat.format(I18N.getString(
+                        "message.module-version"),
+                        oversion.get().toString(),
+                        JLinkBundlerHelper.getMainModule(params)));
+                appVersion = oversion.get().toString();
+            }
+        }
+
+        return appVersion;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ToolValidator.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+
+public final class ToolValidator {
+
+    ToolValidator(String tool) {
+        this(Path.of(tool));
+    }
+
+    ToolValidator(Path toolPath) {
+        this.toolPath = toolPath;
+        args = new ArrayList<>();
+
+        if (Platform.getPlatform() == Platform.LINUX) {
+            setCommandLine("--version");
+        }
+
+        setToolNotFoundErrorHandler(null);
+        setToolOldVersionErrorHandler(null);
+    }
+
+    ToolValidator setCommandLine(String... args) {
+        this.args = List.of(args);
+        return this;
+    }
+
+    ToolValidator setMinimalVersion(Comparable<String> v) {
+        minimalVersion = v;
+        return this;
+    }
+
+    ToolValidator setVersionParser(Function<Stream<String>, String> v) {
+        versionParser = v;
+        return this;
+    }
+
+    ToolValidator setToolNotFoundErrorHandler(
+            BiFunction<String, IOException, ConfigException> v) {
+        toolNotFoundErrorHandler = v;
+        return this;
+    }
+
+    ToolValidator setToolOldVersionErrorHandler(BiFunction<String, String, ConfigException> v) {
+        toolOldVersionErrorHandler = v;
+        return this;
+    }
+
+    ConfigException validate() {
+        List<String> cmdline = new ArrayList<>();
+        cmdline.add(toolPath.toString());
+        cmdline.addAll(args);
+
+        String name = toolPath.getFileName().toString();
+        try {
+            ProcessBuilder pb = new ProcessBuilder(cmdline);
+            AtomicBoolean canUseTool = new AtomicBoolean();
+            if (minimalVersion == null) {
+                // No version check.
+                canUseTool.setPlain(true);
+            }
+
+            String[] version = new String[1];
+            Executor.of(pb).setOutputConsumer(lines -> {
+                if (versionParser != null && minimalVersion != null) {
+                    version[0] = versionParser.apply(lines);
+                    if (minimalVersion.compareTo(version[0]) < 0) {
+                        canUseTool.setPlain(true);
+                    }
+                }
+            }).execute();
+
+            if (!canUseTool.getPlain()) {
+                if (toolOldVersionErrorHandler != null) {
+                    return toolOldVersionErrorHandler.apply(name, version[0]);
+                }
+                return new ConfigException(MessageFormat.format(I18N.getString(
+                        "error.tool-old-version"), name, minimalVersion),
+                        MessageFormat.format(I18N.getString(
+                                "error.tool-old-version.advice"), name,
+                                minimalVersion));
+            }
+        } catch (IOException e) {
+            if (toolNotFoundErrorHandler != null) {
+                return toolNotFoundErrorHandler.apply(name, e);
+            }
+            return new ConfigException(MessageFormat.format(I18N.getString(
+                    "error.tool-not-found"), name, e.getMessage()),
+                    MessageFormat.format(I18N.getString(
+                            "error.tool-not-found.advice"), name), e);
+        }
+
+        // All good. Tool can be used.
+        return null;
+    }
+
+    private final Path toolPath;
+    private List<String> args;
+    private Comparable<String> minimalVersion;
+    private Function<Stream<String>, String> versionParser;
+    private BiFunction<String, IOException, ConfigException> toolNotFoundErrorHandler;
+    private BiFunction<String, String, ConfigException> toolOldVersionErrorHandler;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ValidOptions.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2018, 2019, 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.incubator.jpackage.internal;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import jdk.incubator.jpackage.internal.Arguments.CLIOptions;
+
+/**
+ * ValidOptions
+ *
+ * Two basic methods for validating command line options.
+ *
+ * initArgs()
+ *      Computes the Map of valid options for each mode on this Platform.
+ *
+ * checkIfSupported(CLIOptions arg)
+ *      Determine if the given arg is valid on this platform.
+ *
+ * checkIfImageSupported(CLIOptions arg)
+ *      Determine if the given arg is valid for creating app image.
+ *
+ * checkIfInstallerSupported(CLIOptions arg)
+ *      Determine if the given arg is valid for creating installer.
+ *
+ */
+class ValidOptions {
+
+    enum USE {
+        ALL,        // valid in all cases
+        LAUNCHER,   // valid when creating a launcher
+        INSTALL     // valid when creating an installer
+    }
+
+    private static final HashMap<String, USE> options = new HashMap<>();
+
+
+    // initializing list of mandatory arguments
+    static {
+        options.put(CLIOptions.NAME.getId(), USE.ALL);
+        options.put(CLIOptions.VERSION.getId(), USE.ALL);
+        options.put(CLIOptions.OUTPUT.getId(), USE.ALL);
+        options.put(CLIOptions.TEMP_ROOT.getId(), USE.ALL);
+        options.put(CLIOptions.VERBOSE.getId(), USE.ALL);
+        options.put(CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId(), USE.ALL);
+        options.put(CLIOptions.RESOURCE_DIR.getId(), USE.ALL);
+        options.put(CLIOptions.DESCRIPTION.getId(), USE.ALL);
+        options.put(CLIOptions.VENDOR.getId(), USE.ALL);
+        options.put(CLIOptions.COPYRIGHT.getId(), USE.ALL);
+        options.put(CLIOptions.PACKAGE_TYPE.getId(), USE.ALL);
+
+        options.put(CLIOptions.INPUT.getId(), USE.LAUNCHER);
+        options.put(CLIOptions.MODULE.getId(), USE.LAUNCHER);
+        options.put(CLIOptions.MODULE_PATH.getId(), USE.LAUNCHER);
+        options.put(CLIOptions.ADD_MODULES.getId(), USE.LAUNCHER);
+        options.put(CLIOptions.MAIN_JAR.getId(), USE.LAUNCHER);
+        options.put(CLIOptions.APPCLASS.getId(), USE.LAUNCHER);
+        options.put(CLIOptions.ICON.getId(), USE.LAUNCHER);
+        options.put(CLIOptions.ARGUMENTS.getId(), USE.LAUNCHER);
+        options.put(CLIOptions.JAVA_OPTIONS.getId(), USE.LAUNCHER);
+        options.put(CLIOptions.ADD_LAUNCHER.getId(), USE.LAUNCHER);
+        options.put(CLIOptions.BIND_SERVICES.getId(), USE.LAUNCHER);
+
+        options.put(CLIOptions.LICENSE_FILE.getId(), USE.INSTALL);
+        options.put(CLIOptions.INSTALL_DIR.getId(), USE.INSTALL);
+        options.put(CLIOptions.PREDEFINED_APP_IMAGE.getId(), USE.INSTALL);
+
+        options.put(CLIOptions.FILE_ASSOCIATIONS.getId(),
+            (Platform.getPlatform() == Platform.MAC) ?  USE.ALL : USE.INSTALL);
+
+        if (Platform.getPlatform() == Platform.WINDOWS) {
+            options.put(CLIOptions.WIN_CONSOLE_HINT.getId(), USE.LAUNCHER);
+
+            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_DIR_CHOOSER.getId(), USE.INSTALL);
+            options.put(CLIOptions.WIN_UPGRADE_UUID.getId(), USE.INSTALL);
+            options.put(CLIOptions.WIN_PER_USER_INSTALLATION.getId(),
+                    USE.INSTALL);
+        }
+
+        if (Platform.getPlatform() == Platform.MAC) {
+            options.put(CLIOptions.MAC_SIGN.getId(), USE.ALL);
+            options.put(CLIOptions.MAC_BUNDLE_NAME.getId(), USE.ALL);
+            options.put(CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(), USE.ALL);
+            options.put(CLIOptions.MAC_BUNDLE_SIGNING_PREFIX.getId(),
+                    USE.ALL);
+            options.put(CLIOptions.MAC_SIGNING_KEY_NAME.getId(), USE.ALL);
+            options.put(CLIOptions.MAC_SIGNING_KEYCHAIN.getId(), USE.ALL);
+            options.put(CLIOptions.MAC_APP_STORE_ENTITLEMENTS.getId(),
+                    USE.ALL);
+        }
+
+        if (Platform.getPlatform() == Platform.LINUX) {
+            options.put(CLIOptions.LINUX_BUNDLE_NAME.getId(), USE.INSTALL);
+            options.put(CLIOptions.LINUX_DEB_MAINTAINER.getId(), USE.INSTALL);
+            options.put(CLIOptions.LINUX_CATEGORY.getId(), USE.INSTALL);
+            options.put(CLIOptions.LINUX_RPM_LICENSE_TYPE.getId(), USE.INSTALL);
+            options.put(CLIOptions.LINUX_PACKAGE_DEPENDENCIES.getId(),
+                    USE.INSTALL);
+            options.put(CLIOptions.LINUX_MENU_GROUP.getId(), USE.INSTALL);
+            options.put(CLIOptions.RELEASE.getId(), USE.INSTALL);
+            options.put(CLIOptions.LINUX_SHORTCUT_HINT.getId(), USE.INSTALL);
+        }
+    }
+
+    static boolean checkIfSupported(CLIOptions arg) {
+        return options.containsKey(arg.getId());
+    }
+
+    static boolean checkIfImageSupported(CLIOptions arg) {
+        USE use = options.get(arg.getId());
+        return USE.ALL == use || USE.LAUNCHER == use;
+    }
+
+    static boolean checkIfInstallerSupported(CLIOptions arg) {
+        USE use = options.get(arg.getId());
+        return USE.ALL == use || USE.INSTALL == use;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/HelpResources.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,274 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+MSG_Help=Usage: jpackage <options>\n\
+\n\
+Sample usages:\n\
+--------------\n\
+\    Generate a non-modular application image:\n\
+\        jpackage -t app-image -d destdir -i inputdir -n name \\\n\
+\            --main-class className --main-jar MyJar.jar\n\
+\    Generate a modular application image:\n\
+\        jpackage -t app-image -n name -p modulePath \\\n\
+\            -m moduleName/className\n\
+\        To provide your own options to jlink, run jlink separately:\n\
+\            jlink --output appRuntimeImage -p ModulePath -m moduleName \\\n\
+\                --no-header-files [<additional jlink options>...]\n\
+\            jpackage -t app-image -n name \\\n\
+\                -m moduleName/className --runtime-image appRuntimeImage\n\
+\    Generate an application package:\n\
+\        jpackage -t <type> -n name \\\n\
+\            -p modulePath -m moduleName/className\n\
+\        jpackage -t <type> -i inputdir -n name \\\n\
+\            --main-class package.ClassName --main-jar MyJar.jar\n\
+\        jpackage -t <type> -n name \\\n\
+\            --app-image <app image dir>\n\
+\    Generate a Java runtime package:\n\
+\        jpackage -n name --runtime-image <runtime-image>\n\
+\n\
+Generic Options:\n\
+\  @<filename> \n\
+\          Read options and/or mode from a file \n\
+\          This option can be used multiple times.\n\
+\  --type -t <type> \n\
+\          The type of package to create\n\
+\          Valid values are: {1} \n\
+\          If this option is not specified a platform dependent\n\
+\          default type will be created.\n\
+\  --app-version <version>\n\
+\          Version of the application and/or package\n\
+\  --copyright <copyright string>\n\
+\          Copyright for the application\n\
+\  --description <description string>\n\
+\          Description of the application\n\
+\  --help -h \n\
+\          Print the usage text with a list and description of each valid\n\
+\          option for the current platform to the output stream, and exit\n\
+\  --name -n <name>\n\
+\          Name of the application and/or package\n\
+\  --dest -d <destination path>\n\
+\          Path where generated output file is placed\n\
+\          Defaults to the current working directory.\n\
+\          (absolute path or relative to the current directory)\n\
+\  --temp <file path>\n\
+\          Path of a new or empty directory used to create temporary files\n\
+\          (absolute path or relative to the current directory)\n\
+\          If specified, the temp dir will not be removed upon the task\n\
+\          completion and must be removed manually\n\
+\          If not specified, a temporary directory will be created and\n\
+\          removed upon the task completion.\n\
+\  --vendor <vendor string>\n\
+\          Vendor of the application\n\
+\  --verbose\n\
+\          Enables verbose output\n\
+\  --version\n\
+\          Print the product version to the output stream and exit\n\
+\n\
+\Options for creating the runtime image:\n\
+\  --add-modules <module name>[,<module name>...]\n\
+\          A comma (",") separated list of modules to add.\n\
+\          This module list, along with the main module (if specified)\n\
+\          will be passed to jlink as the --add-module argument.\n\
+\          if not specified, either just the main module (if --module is\n\
+\          specified), or the default set of modules (if --main-jar is \n\
+\          specified) are used.\n\
+\          This option can be used multiple times.\n\
+\  --module-path -p <module path>...\n\
+\          A {0} separated list of paths\n\
+\          Each path is either a directory of modules or the path to a\n\
+\          modular jar.\n\
+\          (each path is absolute or relative to the current directory)\n\
+\          This option can be used multiple times.\n\
+\  --bind-services \n\
+\          Pass on --bind-services option to jlink (which will link in \n\
+\          service provider modules and their dependences) \n\
+\  --runtime-image <file path>\n\
+\          Path of the predefined runtime image that will be copied into\n\
+\          the application image\n\
+\          (absolute path or relative to the current directory)\n\
+\          If --runtime-image is not specified, jpackage will run jlink to\n\
+\          create the runtime image using options:\n\
+\          --strip-debug, --no-header-files, --no-man-pages, and\n\
+\          --strip-native-commands.  --bind-services will also be added if\n\
+\          --add-modules is not specified.\n\
+\n\
+\Options for creating the application image:\n\
+\  --icon <icon file path>\n\
+\          Path of the icon of the application package\n\
+\          (absolute path or relative to the current directory)\n\
+\  --input -i <input path>\n\
+\          Path of the input directory that contains the files to be packaged\n\
+\          (absolute path or relative to the current directory)\n\
+\          All files in the input directory will be packaged into the\n\
+\          application image.\n\
+\n\
+\Options for creating the application launcher(s):\n\
+\  --add-launcher <launcher name>=<file path>\n\
+\          Name of launcher, and a path to a Properties file that contains\n\
+\          a list of key, value pairs\n\
+\          (absolute path or relative to the current directory)\n\
+\          The keys "module", "main-jar", "main-class",\n\
+\          "arguments", "java-options", "app-version", "icon", and\n\
+\          "win-console" can be used.\n\
+\          These options are added to, or used to overwrite, the original\n\
+\          command line options to build an additional alternative launcher.\n\
+\          The main application launcher will be built from the command line\n\
+\          options. Additional alternative launchers can be built using\n\
+\          this option, and this option can be used multiple times to\n\
+\          build multiple additional launchers. \n\
+\  --arguments <main class arguments>\n\
+\          Command line arguments to pass to the main class if no command\n\
+\          line arguments are given to the launcher\n\
+\          This option can be used multiple times.\n\
+\  --java-options <java options>\n\
+\          Options to pass to the Java runtime\n\
+\          This option can be used multiple times.\n\
+\  --main-class <class name>\n\
+\          Qualified name of the application main class to execute\n\
+\          This option can only be used if --main-jar is specified.\n\
+\  --main-jar <main jar file>\n\
+\          The main JAR of the application; containing the main class\n\
+\          (specified as a path relative to the input path)\n\
+\          Either --module or --main-jar option can be specified but not\n\
+\          both.\n\
+\  --module -m <module name>[/<main class>]\n\
+\          The main module (and optionally main class) of the application\n\
+\          This module must be located on the module path.\n\
+\          When this option is specified, the main module will be linked\n\
+\          in the Java runtime image.  Either --module or --main-jar\n\
+\          option can be specified but not both.\n\
+{2}\n\
+\Options for creating the application package:\n\
+\  --app-image <file path>\n\
+\          Location of the predefined application image that is used\n\
+\          to build an installable package\n\
+\          (absolute path or relative to the current directory)\n\
+\  --file-associations <file path>\n\
+\          Path to a Properties file that contains list of key, value pairs\n\
+\          (absolute path or relative to the current directory)\n\
+\          The keys "extension", "mime-type", "icon", and "description"\n\
+\          can be used to describe the association.\n\
+\          This option can be used multiple times.\n\
+\  --install-dir <file path>\n\
+\          {4}\
+\  --license-file <file path>\n\
+\          Path to the license file\n\
+\          (absolute path or relative to the current directory)\n\
+\  --resource-dir <path>\n\
+\          Path to override jpackage resources\n\
+\          Icons, template files, and other resources of jpackage can be\n\
+\          over-ridden by adding replacement resources to this directory.\n\
+\          (absolute path or relative to the current directory)\n\
+\  --runtime-image <file-path>\n\
+\          Path of the predefined runtime image to install\n\
+\          (absolute path or relative to the current directory)\n\
+\          Option is required when creating a runtime package.\n\
+\n\
+\Platform dependent options for creating the application package:\n\
+{3}
+
+MSG_Help_win_launcher=\
+\n\
+\Platform dependent option for creating the application launcher:\n\
+\  --win-console\n\
+\          Creates a console launcher for the application, should be\n\
+\          specified for application which requires console interactions\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\
+\          Adds the application to the system menu\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\
+\  --win-upgrade-uuid <id string>\n\
+\          UUID associated with upgrades for this package\n\
+
+MSG_Help_win_install_dir=\
+\Relative sub-path under the default installation location\n\
+
+MSG_Help_mac_launcher=\
+\  --mac-package-identifier <ID string>\n\
+\          An identifier that uniquely identifies the application for macOS\n\
+\          Defaults to the main class name.\n\
+\          May only use alphanumeric (A-Z,a-z,0-9), hyphen (-),\n\
+\          and period (.) characters.\n\
+\  --mac-package-name <name string>\n\
+\          Name of the application as it appears in the Menu Bar\n\
+\          This can be different from the application name.\n\
+\          This name must be less than 16 characters long and be suitable for\n\
+\          displaying in the menu bar and the application Info window.\n\
+\          Defaults to the application name.\n\
+\  --mac-package-signing-prefix <prefix string>\n\
+\          When signing the application package, this value is prefixed\n\
+\          to all components that need to be signed that don't have\n\
+\          an existing package identifier.\n\
+\  --mac-sign\n\
+\          Request that the package be signed\n\
+\  --mac-signing-keychain <file path>\n\
+\          Path of the keychain to search for the signing identity\n\
+\          (absolute path or relative to the current directory).\n\
+\          If not specified, the standard keychains are used.\n\
+\  --mac-signing-key-user-name <team name>\n\
+\          Team name portion in Apple signing identities' names.\n\
+\          For example "Developer ID Application: "\n\
+
+MSG_Help_linux_install=\
+\  --linux-package-name <package name>\n\
+\          Name for Linux package, defaults to the application name\n\
+\  --linux-deb-maintainer <email address>\n\
+\          Maintainer for .deb package\n\
+\  --linux-menu-group <menu-group-name>\n\
+\          Menu group this application is placed in\n\
+\  --linux-package-deps\n\
+\          Required packages or capabilities for the application\n\
+\  --linux-rpm-license-type <type string>\n\
+\          Type of the license ("License: <value>" of the RPM .spec)\n\
+\  --linux-app-release <release value>\n\
+\          Release value of the RPM <name>.spec file or \n\
+\          Debian revision value of the DEB control file.\n\
+\  --linux-app-category <category value>\n\
+\          Group value of the RPM <name>.spec file or \n\
+\          Section value of DEB control file.\n\
+\  --linux-shortcut\n\
+\          Creates a shortcut for the application\n\
+
+MSG_Help_mac_linux_install_dir=\
+\Absolute path of the installation directory of the application\n\
+
+MSG_Help_default_install_dir=\
+\Absolute path of the installation directory of the application on OS X\n\
+\          or Linux. Relative sub-path of the installation location of\n\
+\          the application such as "Program Files" or "AppData" on Windows.\n\
+
+MSG_Help_no_args=Usage: jpackage <mode> <options>\n\
+\Use jpackage --help (or -h) for a list of possible options\
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/HelpResources_ja.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,274 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+MSG_Help=Usage: jpackage <options>\n\
+\n\
+Sample usages:\n\
+--------------\n\
+\    Generate a non-modular application image:\n\
+\        jpackage -t app-image -d destdir -i inputdir -n name \\\n\
+\            --main-class className --main-jar MyJar.jar\n\
+\    Generate a modular application image:\n\
+\        jpackage -t app-image -n name -p modulePath \\\n\
+\            -m moduleName/className\n\
+\        To provide your own options to jlink, run jlink separately:\n\
+\            jlink --output appRuntimeImage -p ModulePath -m moduleName \\\n\
+\                --no-header-files [<additional jlink options>...]\n\
+\            jpackage -t app-image -n name \\\n\
+\                -m moduleName/className --runtime-image appRuntimeImage\n\
+\    Generate an application package:\n\
+\        jpackage -t <type> -n name \\\n\
+\            -p modulePath -m moduleName/className\n\
+\        jpackage -t <type> -i inputdir -n name \\\n\
+\            --main-class package.ClassName --main-jar MyJar.jar\n\
+\        jpackage -t <type> -n name \\\n\
+\            --app-image <app image dir>\n\
+\    Generate a Java runtime package:\n\
+\        jpackage -n name --runtime-image <runtime-image>\n\
+\n\
+Generic Options:\n\
+\  @<filename> \n\
+\          Read options and/or mode from a file \n\
+\          This option can be used multiple times.\n\
+\  --type -t <type> \n\
+\          The type of package to create\n\
+\          Valid values are: {1} \n\
+\          If this option is not specified a platform dependent\n\
+\          default type will be created.\n\
+\  --app-version <version>\n\
+\          Version of the application and/or package\n\
+\  --copyright <copyright string>\n\
+\          Copyright for the application\n\
+\  --description <description string>\n\
+\          Description of the application\n\
+\  --help -h \n\
+\          Print the usage text with a list and description of each valid\n\
+\          option for the current platform to the output stream, and exit\n\
+\  --name -n <name>\n\
+\          Name of the application and/or package\n\
+\  --dest -d <destination path>\n\
+\          Path where generated output file is placed\n\
+\          Defaults to the current working directory.\n\
+\          (absolute path or relative to the current directory)\n\
+\  --temp <file path>\n\
+\          Path of a new or empty directory used to create temporary files\n\
+\          (absolute path or relative to the current directory)\n\
+\          If specified, the temp dir will not be removed upon the task\n\
+\          completion and must be removed manually\n\
+\          If not specified, a temporary directory will be created and\n\
+\          removed upon the task completion.\n\
+\  --vendor <vendor string>\n\
+\          Vendor of the application\n\
+\  --verbose\n\
+\          Enables verbose output\n\
+\  --version\n\
+\          Print the product version to the output stream and exit\n\
+\n\
+\Options for creating the runtime image:\n\
+\  --add-modules <module name>[,<module name>...]\n\
+\          A comma (",") separated list of modules to add.\n\
+\          This module list, along with the main module (if specified)\n\
+\          will be passed to jlink as the --add-module argument.\n\
+\          if not specified, either just the main module (if --module is\n\
+\          specified), or the default set of modules (if --main-jar is \n\
+\          specified) are used.\n\
+\          This option can be used multiple times.\n\
+\  --module-path -p <module path>...\n\
+\          A {0} separated list of paths\n\
+\          Each path is either a directory of modules or the path to a\n\
+\          modular jar.\n\
+\          (each path is absolute or relative to the current directory)\n\
+\          This option can be used multiple times.\n\
+\  --bind-services \n\
+\          Pass on --bind-services option to jlink (which will link in \n\
+\          service provider modules and their dependences) \n\
+\  --runtime-image <file path>\n\
+\          Path of the predefined runtime image that will be copied into\n\
+\          the application image\n\
+\          (absolute path or relative to the current directory)\n\
+\          If --runtime-image is not specified, jpackage will run jlink to\n\
+\          create the runtime image using options:\n\
+\          --strip-debug, --no-header-files, --no-man-pages, and\n\
+\          --strip-native-commands.  --bind-services will also be added if\n\
+\          --add-modules is not specified.\n\
+\n\
+\Options for creating the application image:\n\
+\  --icon <icon file path>\n\
+\          Path of the icon of the application package\n\
+\          (absolute path or relative to the current directory)\n\
+\  --input -i <input path>\n\
+\          Path of the input directory that contains the files to be packaged\n\
+\          (absolute path or relative to the current directory)\n\
+\          All files in the input directory will be packaged into the\n\
+\          application image.\n\
+\n\
+\Options for creating the application launcher(s):\n\
+\  --add-launcher <launcher name>=<file path>\n\
+\          Name of launcher, and a path to a Properties file that contains\n\
+\          a list of key, value pairs\n\
+\          (absolute path or relative to the current directory)\n\
+\          The keys "module", "main-jar", "main-class",\n\
+\          "arguments", "java-options", "app-version", "icon", and\n\
+\          "win-console" can be used.\n\
+\          These options are added to, or used to overwrite, the original\n\
+\          command line options to build an additional alternative launcher.\n\
+\          The main application launcher will be built from the command line\n\
+\          options. Additional alternative launchers can be built using\n\
+\          this option, and this option can be used multiple times to\n\
+\          build multiple additional launchers. \n\
+\  --arguments <main class arguments>\n\
+\          Command line arguments to pass to the main class if no command\n\
+\          line arguments are given to the launcher\n\
+\          This option can be used multiple times.\n\
+\  --java-options <java options>\n\
+\          Options to pass to the Java runtime\n\
+\          This option can be used multiple times.\n\
+\  --main-class <class name>\n\
+\          Qualified name of the application main class to execute\n\
+\          This option can only be used if --main-jar is specified.\n\
+\  --main-jar <main jar file>\n\
+\          The main JAR of the application; containing the main class\n\
+\          (specified as a path relative to the input path)\n\
+\          Either --module or --main-jar option can be specified but not\n\
+\          both.\n\
+\  --module -m <module name>[/<main class>]\n\
+\          The main module (and optionally main class) of the application\n\
+\          This module must be located on the module path.\n\
+\          When this option is specified, the main module will be linked\n\
+\          in the Java runtime image.  Either --module or --main-jar\n\
+\          option can be specified but not both.\n\
+{2}\n\
+\Options for creating the application package:\n\
+\  --app-image <file path>\n\
+\          Location of the predefined application image that is used\n\
+\          to build an installable package\n\
+\          (absolute path or relative to the current directory)\n\
+\  --file-associations <file path>\n\
+\          Path to a Properties file that contains list of key, value pairs\n\
+\          (absolute path or relative to the current directory)\n\
+\          The keys "extension", "mime-type", "icon", and "description"\n\
+\          can be used to describe the association.\n\
+\          This option can be used multiple times.\n\
+\  --install-dir <file path>\n\
+\          {4}\
+\  --license-file <file path>\n\
+\          Path to the license file\n\
+\          (absolute path or relative to the current directory)\n\
+\  --resource-dir <path>\n\
+\          Path to override jpackage resources\n\
+\          Icons, template files, and other resources of jpackage can be\n\
+\          over-ridden by adding replacement resources to this directory.\n\
+\          (absolute path or relative to the current directory)\n\
+\  --runtime-image <file-path>\n\
+\          Path of the predefined runtime image to install\n\
+\          (absolute path or relative to the current directory)\n\
+\          Option is required when creating a runtime package.\n\
+\n\
+\Platform dependent options for creating the application package:\n\
+{3}
+
+MSG_Help_win_launcher=\
+\n\
+\Platform dependent option for creating the application launcher:\n\
+\  --win-console\n\
+\          Creates a console launcher for the application, should be\n\
+\          specified for application which requires console interactions\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\
+\          Adds the application to the system menu\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\
+\  --win-upgrade-uuid <id string>\n\
+\          UUID associated with upgrades for this package\n\
+
+MSG_Help_win_install_dir=\
+\Relative sub-path under the default installation location\n\
+
+MSG_Help_mac_launcher=\
+\  --mac-package-identifier <ID string>\n\
+\          An identifier that uniquely identifies the application for macOS\n\
+\          Defaults to the main class name.\n\
+\          May only use alphanumeric (A-Z,a-z,0-9), hyphen (-),\n\
+\          and period (.) characters.\n\
+\  --mac-package-name <name string>\n\
+\          Name of the application as it appears in the Menu Bar\n\
+\          This can be different from the application name.\n\
+\          This name must be less than 16 characters long and be suitable for\n\
+\          displaying in the menu bar and the application Info window.\n\
+\          Defaults to the application name.\n\
+\  --mac-package-signing-prefix <prefix string>\n\
+\          When signing the application package, this value is prefixed\n\
+\          to all components that need to be signed that don't have\n\
+\          an existing package identifier.\n\
+\  --mac-sign\n\
+\          Request that the package be signed\n\
+\  --mac-signing-keychain <file path>\n\
+\          Path of the keychain to search for the signing identity\n\
+\          (absolute path or relative to the current directory).\n\
+\          If not specified, the standard keychains are used.\n\
+\  --mac-signing-key-user-name <team name>\n\
+\          Team name portion in Apple signing identities' names.\n\
+\          For example "Developer ID Application: "\n\
+
+MSG_Help_linux_install=\
+\  --linux-package-name <package name>\n\
+\          Name for Linux package, defaults to the application name\n\
+\  --linux-deb-maintainer <email address>\n\
+\          Maintainer for .deb package\n\
+\  --linux-menu-group <menu-group-name>\n\
+\          Menu group this application is placed in\n\
+\  --linux-package-deps\n\
+\          Required packages or capabilities for the application\n\
+\  --linux-rpm-license-type <type string>\n\
+\          Type of the license ("License: <value>" of the RPM .spec)\n\
+\  --linux-app-release <release value>\n\
+\          Release value of the RPM <name>.spec file or \n\
+\          Debian revision value of the DEB control file.\n\
+\  --linux-app-category <category value>\n\
+\          Group value of the RPM <name>.spec file or \n\
+\          Section value of DEB control file.\n\
+\  --linux-shortcut\n\
+\          Creates a shortcut for the application\n\
+
+MSG_Help_mac_linux_install_dir=\
+\Absolute path of the installation directory of the application\n\
+
+MSG_Help_default_install_dir=\
+\Absolute path of the installation directory of the application on OS X\n\
+\          or Linux. Relative sub-path of the installation location of\n\
+\          the application such as "Program Files" or "AppData" on Windows.\n\
+
+MSG_Help_no_args=Usage: jpackage <mode> <options>\n\
+\Use jpackage --help (or -h) for a list of possible options\
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/HelpResources_zh_CN.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,274 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+MSG_Help=Usage: jpackage <options>\n\
+\n\
+Sample usages:\n\
+--------------\n\
+\    Generate a non-modular application image:\n\
+\        jpackage -t app-image -d destdir -i inputdir -n name \\\n\
+\            --main-class className --main-jar MyJar.jar\n\
+\    Generate a modular application image:\n\
+\        jpackage -t app-image -n name -p modulePath \\\n\
+\            -m moduleName/className\n\
+\        To provide your own options to jlink, run jlink separately:\n\
+\            jlink --output appRuntimeImage -p ModulePath -m moduleName \\\n\
+\                --no-header-files [<additional jlink options>...]\n\
+\            jpackage -t app-image -n name \\\n\
+\                -m moduleName/className --runtime-image appRuntimeImage\n\
+\    Generate an application package:\n\
+\        jpackage -t <type> -n name \\\n\
+\            -p modulePath -m moduleName/className\n\
+\        jpackage -t <type> -i inputdir -n name \\\n\
+\            --main-class package.ClassName --main-jar MyJar.jar\n\
+\        jpackage -t <type> -n name \\\n\
+\            --app-image <app image dir>\n\
+\    Generate a Java runtime package:\n\
+\        jpackage -n name --runtime-image <runtime-image>\n\
+\n\
+Generic Options:\n\
+\  @<filename> \n\
+\          Read options and/or mode from a file \n\
+\          This option can be used multiple times.\n\
+\  --type -t <type> \n\
+\          The type of package to create\n\
+\          Valid values are: {1} \n\
+\          If this option is not specified a platform dependent\n\
+\          default type will be created.\n\
+\  --app-version <version>\n\
+\          Version of the application and/or package\n\
+\  --copyright <copyright string>\n\
+\          Copyright for the application\n\
+\  --description <description string>\n\
+\          Description of the application\n\
+\  --help -h \n\
+\          Print the usage text with a list and description of each valid\n\
+\          option for the current platform to the output stream, and exit\n\
+\  --name -n <name>\n\
+\          Name of the application and/or package\n\
+\  --dest -d <destination path>\n\
+\          Path where generated output file is placed\n\
+\          Defaults to the current working directory.\n\
+\          (absolute path or relative to the current directory)\n\
+\  --temp <file path>\n\
+\          Path of a new or empty directory used to create temporary files\n\
+\          (absolute path or relative to the current directory)\n\
+\          If specified, the temp dir will not be removed upon the task\n\
+\          completion and must be removed manually\n\
+\          If not specified, a temporary directory will be created and\n\
+\          removed upon the task completion.\n\
+\  --vendor <vendor string>\n\
+\          Vendor of the application\n\
+\  --verbose\n\
+\          Enables verbose output\n\
+\  --version\n\
+\          Print the product version to the output stream and exit\n\
+\n\
+\Options for creating the runtime image:\n\
+\  --add-modules <module name>[,<module name>...]\n\
+\          A comma (",") separated list of modules to add.\n\
+\          This module list, along with the main module (if specified)\n\
+\          will be passed to jlink as the --add-module argument.\n\
+\          if not specified, either just the main module (if --module is\n\
+\          specified), or the default set of modules (if --main-jar is \n\
+\          specified) are used.\n\
+\          This option can be used multiple times.\n\
+\  --module-path -p <module path>...\n\
+\          A {0} separated list of paths\n\
+\          Each path is either a directory of modules or the path to a\n\
+\          modular jar.\n\
+\          (each path is absolute or relative to the current directory)\n\
+\          This option can be used multiple times.\n\
+\  --bind-services \n\
+\          Pass on --bind-services option to jlink (which will link in \n\
+\          service provider modules and their dependences) \n\
+\  --runtime-image <file path>\n\
+\          Path of the predefined runtime image that will be copied into\n\
+\          the application image\n\
+\          (absolute path or relative to the current directory)\n\
+\          If --runtime-image is not specified, jpackage will run jlink to\n\
+\          create the runtime image using options:\n\
+\          --strip-debug, --no-header-files, --no-man-pages, and\n\
+\          --strip-native-commands.  --bind-services will also be added if\n\
+\          --add-modules is not specified.\n\
+\n\
+\Options for creating the application image:\n\
+\  --icon <icon file path>\n\
+\          Path of the icon of the application package\n\
+\          (absolute path or relative to the current directory)\n\
+\  --input -i <input path>\n\
+\          Path of the input directory that contains the files to be packaged\n\
+\          (absolute path or relative to the current directory)\n\
+\          All files in the input directory will be packaged into the\n\
+\          application image.\n\
+\n\
+\Options for creating the application launcher(s):\n\
+\  --add-launcher <launcher name>=<file path>\n\
+\          Name of launcher, and a path to a Properties file that contains\n\
+\          a list of key, value pairs\n\
+\          (absolute path or relative to the current directory)\n\
+\          The keys "module", "main-jar", "main-class",\n\
+\          "arguments", "java-options", "app-version", "icon", and\n\
+\          "win-console" can be used.\n\
+\          These options are added to, or used to overwrite, the original\n\
+\          command line options to build an additional alternative launcher.\n\
+\          The main application launcher will be built from the command line\n\
+\          options. Additional alternative launchers can be built using\n\
+\          this option, and this option can be used multiple times to\n\
+\          build multiple additional launchers. \n\
+\  --arguments <main class arguments>\n\
+\          Command line arguments to pass to the main class if no command\n\
+\          line arguments are given to the launcher\n\
+\          This option can be used multiple times.\n\
+\  --java-options <java options>\n\
+\          Options to pass to the Java runtime\n\
+\          This option can be used multiple times.\n\
+\  --main-class <class name>\n\
+\          Qualified name of the application main class to execute\n\
+\          This option can only be used if --main-jar is specified.\n\
+\  --main-jar <main jar file>\n\
+\          The main JAR of the application; containing the main class\n\
+\          (specified as a path relative to the input path)\n\
+\          Either --module or --main-jar option can be specified but not\n\
+\          both.\n\
+\  --module -m <module name>[/<main class>]\n\
+\          The main module (and optionally main class) of the application\n\
+\          This module must be located on the module path.\n\
+\          When this option is specified, the main module will be linked\n\
+\          in the Java runtime image.  Either --module or --main-jar\n\
+\          option can be specified but not both.\n\
+{2}\n\
+\Options for creating the application package:\n\
+\  --app-image <file path>\n\
+\          Location of the predefined application image that is used\n\
+\          to build an installable package\n\
+\          (absolute path or relative to the current directory)\n\
+\  --file-associations <file path>\n\
+\          Path to a Properties file that contains list of key, value pairs\n\
+\          (absolute path or relative to the current directory)\n\
+\          The keys "extension", "mime-type", "icon", and "description"\n\
+\          can be used to describe the association.\n\
+\          This option can be used multiple times.\n\
+\  --install-dir <file path>\n\
+\          {4}\
+\  --license-file <file path>\n\
+\          Path to the license file\n\
+\          (absolute path or relative to the current directory)\n\
+\  --resource-dir <path>\n\
+\          Path to override jpackage resources\n\
+\          Icons, template files, and other resources of jpackage can be\n\
+\          over-ridden by adding replacement resources to this directory.\n\
+\          (absolute path or relative to the current directory)\n\
+\  --runtime-image <file-path>\n\
+\          Path of the predefined runtime image to install\n\
+\          (absolute path or relative to the current directory)\n\
+\          Option is required when creating a runtime package.\n\
+\n\
+\Platform dependent options for creating the application package:\n\
+{3}
+
+MSG_Help_win_launcher=\
+\n\
+\Platform dependent option for creating the application launcher:\n\
+\  --win-console\n\
+\          Creates a console launcher for the application, should be\n\
+\          specified for application which requires console interactions\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\
+\          Adds the application to the system menu\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\
+\  --win-upgrade-uuid <id string>\n\
+\          UUID associated with upgrades for this package\n\
+
+MSG_Help_win_install_dir=\
+\Relative sub-path under the default installation location\n\
+
+MSG_Help_mac_launcher=\
+\  --mac-package-identifier <ID string>\n\
+\          An identifier that uniquely identifies the application for macOS\n\
+\          Defaults to the main class name.\n\
+\          May only use alphanumeric (A-Z,a-z,0-9), hyphen (-),\n\
+\          and period (.) characters.\n\
+\  --mac-package-name <name string>\n\
+\          Name of the application as it appears in the Menu Bar\n\
+\          This can be different from the application name.\n\
+\          This name must be less than 16 characters long and be suitable for\n\
+\          displaying in the menu bar and the application Info window.\n\
+\          Defaults to the application name.\n\
+\  --mac-package-signing-prefix <prefix string>\n\
+\          When signing the application package, this value is prefixed\n\
+\          to all components that need to be signed that don't have\n\
+\          an existing package identifier.\n\
+\  --mac-sign\n\
+\          Request that the package be signed\n\
+\  --mac-signing-keychain <file path>\n\
+\          Path of the keychain to search for the signing identity\n\
+\          (absolute path or relative to the current directory).\n\
+\          If not specified, the standard keychains are used.\n\
+\  --mac-signing-key-user-name <team name>\n\
+\          Team name portion in Apple signing identities' names.\n\
+\          For example "Developer ID Application: "\n\
+
+MSG_Help_linux_install=\
+\  --linux-package-name <package name>\n\
+\          Name for Linux package, defaults to the application name\n\
+\  --linux-deb-maintainer <email address>\n\
+\          Maintainer for .deb package\n\
+\  --linux-menu-group <menu-group-name>\n\
+\          Menu group this application is placed in\n\
+\  --linux-package-deps\n\
+\          Required packages or capabilities for the application\n\
+\  --linux-rpm-license-type <type string>\n\
+\          Type of the license ("License: <value>" of the RPM .spec)\n\
+\  --linux-app-release <release value>\n\
+\          Release value of the RPM <name>.spec file or \n\
+\          Debian revision value of the DEB control file.\n\
+\  --linux-app-category <category value>\n\
+\          Group value of the RPM <name>.spec file or \n\
+\          Section value of DEB control file.\n\
+\  --linux-shortcut\n\
+\          Creates a shortcut for the application\n\
+
+MSG_Help_mac_linux_install_dir=\
+\Absolute path of the installation directory of the application\n\
+
+MSG_Help_default_install_dir=\
+\Absolute path of the installation directory of the application on OS X\n\
+\          or Linux. Relative sub-path of the installation location of\n\
+\          the application such as "Program Files" or "AppData" on Windows.\n\
+
+MSG_Help_no_args=Usage: jpackage <mode> <options>\n\
+\Use jpackage --help (or -h) for a list of possible options\
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/MainResources.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,92 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+param.copyright.default=Copyright (C) {0,date,YYYY}
+param.description.default=None
+param.vendor.default=Unknown
+
+message.using-default-resource=Using default package resource {0} {1} (add {2} to the resource-dir to customize).
+message.no-default-resource=no default package resource {0} {1} (add {2} to the resource-dir to customize).
+message.using-custom-resource-from-file=Using custom package resource {0} (loaded from file {1}).
+message.using-custom-resource=Using custom package resource {0} (loaded from {1}).
+message.creating-app-bundle=Creating app package: {0} in {1}
+message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists
+message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
+message.runtime-image-dir-does-not-exist=Specified runtime image directory {0}: {1} does not exists
+message.runtime-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
+message.debug-working-directory=Kept working directory for debug: {0}
+message.bundle-created=Succeeded in building {0} package
+message.module-version=Using version "{0}" from module "{1}" as application version
+message.module-class=Using class "{0}" from module "{1}" as application main class
+
+error.cannot-create-output-dir=Destination directory {0} cannot be created
+error.cannot-write-to-output-dir=Destination directory {0} is not writable
+error.root-exists=Error: Application destination directory {0} already exists
+error.no-main-class-with-main-jar=A main class was not specified nor was one found in the jar {0}
+error.no-main-class-with-main-jar.advice=Specify a main class or ensure that the jar {0} specifies one in the manifest
+error.no-main-class=A main class was not specified nor was one found in the supplied application resources
+error.no-main-class.advice=Please specify a application class or ensure that the appResources has a jar containing one in the manifest
+error.main-jar-does-not-exist=The configured main jar does not exist {0} in the input directory
+error.main-jar-does-not-exist.advice=The main jar must be specified relative to the input directory (not an absolute path), and must exist within that directory
+
+error.tool-not-found=Can not find {0}. Reason: {1}
+error.tool-not-found.advice=Please install {0}
+error.tool-old-version=Can not find {0} {1} or newer
+error.tool-old-version.advice=Please install {0} {1} or newer
+error.jlink.failed=jlink failed with: {0}
+
+warning.module.does.not.exist=Module [{0}] does not exist
+warning.no.jdk.modules.found=Warning: No JDK Modules found
+
+MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
+MSG_BundlerConfigException=Bundler {0} skipped because of a configuration problem: {1} \n\
+Advice to fix: {2}
+MSG_BundlerConfigExceptionNoAdvice=Bundler {0} skipped because of a configuration problem: {1}
+MSG_BundlerRuntimeException=Bundler {0} failed because of {1}
+MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
+
+ERR_NoMainClass=Error: Main application class is missing
+ERR_UnsupportedOption=Error: Option [{0}] is not valid on this platform
+ERR_InvalidTypeOption=Error: Option [{0}] is not valid with type [{1}]
+ERR_NoInstallerEntryPoint=Error: Option [{0}] is not valid without --module or --main-jar entry point option
+
+ERR_MissingArgument=Error: Missing argument: {0}
+ERR_MissingAppResources=Error: No application jars found
+ERR_AppImageNotExist=Error: App image directory "{0}" does not exist
+ERR_NoAddLauncherName=Error: --add-launcher option requires a name and a file path (--add-launcher <name>=<file path>)
+ERR_NoUniqueName=Error: --add-launcher <name>=<file path> requires a unique name
+ERR_NoJreInstallerName=Error: Jre Installers require a name parameter
+ERR_InvalidAppName=Error: Invalid Application name: {0}
+ERR_InvalidSLName=Error: Invalid Add Launcher name: {0}
+ERR_LicenseFileNotExit=Error: Specified license file does not exist
+ERR_BuildRootInvalid=Error: temp ({0}) must be non-existant or empty directory
+ERR_InvalidOption=Error: Invalid Option: [{0}]
+ERR_InvalidInstallerType=Error: Invalid or unsupported type: [{0}]
+ERR_BothMainJarAndModule=Error: Cannot have both --main-jar and --module Options
+ERR_NoEntryPoint=Error: creating application image requires --main-jar or --module Option
+ERR_InputNotDirectory=Error: Input directory specified is not a directory: {0}
+ERR_CannotReadInputDir=Error: No permission to read from input directory: {0}
+ERR_CannotParseOptions=Error: Processing @filename option: {0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/MainResources_ja.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,93 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+param.copyright.default=Copyright (C) {0,date,YYYY}
+param.description.default=None
+param.vendor.default=Unknown
+
+warning.experimental=WARNING: Using experimental tool jpackage
+message.using-default-resource=Using default package resource {0} {1} (add {2} to the resource-dir to customize).
+message.no-default-resource=no default package resource {0} {1} (add {2} to the resource-dir to customize).
+message.using-custom-resource-from-file=Using custom package resource {0} (loaded from file {1}).
+message.using-custom-resource=Using custom package resource {0} (loaded from {1}).
+message.creating-app-bundle=Creating app package: {0} in {1}
+message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists
+message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
+message.runtime-image-dir-does-not-exist=Specified runtime image directory {0}: {1} does not exists
+message.runtime-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
+message.debug-working-directory=Kept working directory for debug: {0}
+message.bundle-created=Succeeded in building {0} package
+message.module-version=Using version "{0}" from module "{1}" as application version
+message.module-class=Using class "{0}" from module "{1}" as application main class
+
+error.cannot-create-output-dir=Destination directory {0} cannot be created
+error.cannot-write-to-output-dir=Destination directory {0} is not writable
+error.root-exists=Error: Application destination directory {0} already exists
+error.no-main-class-with-main-jar=A main class was not specified nor was one found in the jar {0}
+error.no-main-class-with-main-jar.advice=Specify a main class or ensure that the jar {0} specifies one in the manifest
+error.no-main-class=A main class was not specified nor was one found in the supplied application resources
+error.no-main-class.advice=Please specify a application class or ensure that the appResources has a jar containing one in the manifest
+error.main-jar-does-not-exist=The configured main jar does not exist {0} in the input directory
+error.main-jar-does-not-exist.advice=The main jar must be specified relative to the input directory (not an absolute path), and must exist within that directory
+
+error.tool-not-found=Can not find {0}. Reason: {1}
+error.tool-not-found.advice=Please install {0}
+error.tool-old-version=Can not find {0} {1} or newer
+error.tool-old-version.advice=Please install {0} {1} or newer
+error.jlink.failed=jlink failed with: {0}
+
+warning.module.does.not.exist=Module [{0}] does not exist
+warning.no.jdk.modules.found=Warning: No JDK Modules found
+
+MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
+MSG_BundlerConfigException=Bundler {0} skipped because of a configuration problem: {1} \n\
+Advice to fix: {2}
+MSG_BundlerConfigExceptionNoAdvice=Bundler {0} skipped because of a configuration problem: {1}
+MSG_BundlerRuntimeException=Bundler {0} failed because of {1}
+MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
+
+ERR_NoMainClass=Error: Main application class is missing
+ERR_UnsupportedOption=Error: Option [{0}] is not valid on this platform
+ERR_InvalidTypeOption=Error: Option [{0}] is not valid with type [{1}]
+ERR_NoInstallerEntryPoint=Error: Option [{0}] is not valid without --module or --main-jar entry point option
+
+ERR_MissingArgument=Error: Missing argument: {0}
+ERR_MissingAppResources=Error: No application jars found
+ERR_AppImageNotExist=Error: App image directory "{0}" does not exist
+ERR_NoAddLauncherName=Error: --add-launcher option requires a name and a file path (--add-launcher <name>=<file path>)
+ERR_NoUniqueName=Error: --add-launcher <name>=<file path> requires a unique name
+ERR_NoJreInstallerName=Error: Jre Installers require a name parameter
+ERR_InvalidAppName=Error: Invalid Application name: {0}
+ERR_InvalidSLName=Error: Invalid Add Launcher name: {0}
+ERR_LicenseFileNotExit=Error: Specified license file does not exist
+ERR_BuildRootInvalid=Error: temp ({0}) must be non-existant or empty directory
+ERR_InvalidOption=Error: Invalid Option: [{0}]
+ERR_InvalidInstallerType=Error: Invalid or unsupported type: [{0}]
+ERR_BothMainJarAndModule=Error: Cannot have both --main-jar and --module Options
+ERR_NoEntryPoint=Error: creating application image requires --main-jar or --module Option
+ERR_InputNotDirectory=Error: Input directory specified is not a directory: {0}
+ERR_CannotReadInputDir=Error: No permission to read from input directory: {0}
+ERR_CannotParseOptions=Error: Processing @filename option: {0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/MainResources_zh_CN.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,93 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+param.copyright.default=Copyright (C) {0,date,YYYY}
+param.description.default=None
+param.vendor.default=Unknown
+
+warning.experimental=WARNING: Using experimental tool jpackage
+message.using-default-resource=Using default package resource {0} {1} (add {2} to the resource-dir to customize).
+message.no-default-resource=no default package resource {0} {1} (add {2} to the resource-dir to customize).
+message.using-custom-resource-from-file=Using custom package resource {0} (loaded from file {1}).
+message.using-custom-resource=Using custom package resource {0} (loaded from {1}).
+message.creating-app-bundle=Creating app package: {0} in {1}
+message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists
+message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
+message.runtime-image-dir-does-not-exist=Specified runtime image directory {0}: {1} does not exists
+message.runtime-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
+message.debug-working-directory=Kept working directory for debug: {0}
+message.bundle-created=Succeeded in building {0} package
+message.module-version=Using version "{0}" from module "{1}" as application version
+message.module-class=Using class "{0}" from module "{1}" as application main class
+
+error.cannot-create-output-dir=Destination directory {0} cannot be created
+error.cannot-write-to-output-dir=Destination directory {0} is not writable
+error.root-exists=Error: Application destination directory {0} already exists
+error.no-main-class-with-main-jar=A main class was not specified nor was one found in the jar {0}
+error.no-main-class-with-main-jar.advice=Specify a main class or ensure that the jar {0} specifies one in the manifest
+error.no-main-class=A main class was not specified nor was one found in the supplied application resources
+error.no-main-class.advice=Please specify a application class or ensure that the appResources has a jar containing one in the manifest
+error.main-jar-does-not-exist=The configured main jar does not exist {0} in the input directory
+error.main-jar-does-not-exist.advice=The main jar must be specified relative to the input directory (not an absolute path), and must exist within that directory
+
+error.tool-not-found=Can not find {0}. Reason: {1}
+error.tool-not-found.advice=Please install {0}
+error.tool-old-version=Can not find {0} {1} or newer
+error.tool-old-version.advice=Please install {0} {1} or newer
+error.jlink.failed=jlink failed with: {0}
+
+warning.module.does.not.exist=Module [{0}] does not exist
+warning.no.jdk.modules.found=Warning: No JDK Modules found
+
+MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
+MSG_BundlerConfigException=Bundler {0} skipped because of a configuration problem: {1} \n\
+Advice to fix: {2}
+MSG_BundlerConfigExceptionNoAdvice=Bundler {0} skipped because of a configuration problem: {1}
+MSG_BundlerRuntimeException=Bundler {0} failed because of {1}
+MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
+
+ERR_NoMainClass=Error: Main application class is missing
+ERR_UnsupportedOption=Error: Option [{0}] is not valid on this platform
+ERR_InvalidTypeOption=Error: Option [{0}] is not valid with type [{1}]
+ERR_NoInstallerEntryPoint=Error: Option [{0}] is not valid without --module or --main-jar entry point option
+
+ERR_MissingArgument=Error: Missing argument: {0}
+ERR_MissingAppResources=Error: No application jars found
+ERR_AppImageNotExist=Error: App image directory "{0}" does not exist
+ERR_NoAddLauncherName=Error: --add-launcher option requires a name and a file path (--add-launcher <name>=<file path>)
+ERR_NoUniqueName=Error: --add-launcher <name>=<file path> requires a unique name
+ERR_NoJreInstallerName=Error: Jre Installers require a name parameter
+ERR_InvalidAppName=Error: Invalid Application name: {0}
+ERR_InvalidSLName=Error: Invalid Add Launcher name: {0}
+ERR_LicenseFileNotExit=Error: Specified license file does not exist
+ERR_BuildRootInvalid=Error: temp ({0}) must be non-existant or empty directory
+ERR_InvalidOption=Error: Invalid Option: [{0}]
+ERR_InvalidInstallerType=Error: Invalid or unsupported type: [{0}]
+ERR_BothMainJarAndModule=Error: Cannot have both --main-jar and --module Options
+ERR_NoEntryPoint=Error: creating application image requires --main-jar or --module Option
+ERR_InputNotDirectory=Error: Input directory specified is not a directory: {0}
+ERR_CannotReadInputDir=Error: No permission to read from input directory: {0}
+ERR_CannotParseOptions=Error: Processing @filename option: {0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/resources/ResourceLocator.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011, 2019, 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.incubator.jpackage.internal.resources;
+
+/*
+ * ResourceLocator
+ *     This empty class is the only class in this package. Otherwise the
+ * package consists only of resources. ResourceLocator is needed in order
+ * to call getResourceAsStream() to get those resources.
+ */
+
+public class ResourceLocator {
+    public ResourceLocator() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/main/CommandLine.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 1999, 2018, 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.incubator.jpackage.main;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.File;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This file was originally a copy of CommandLine.java in
+ * com.sun.tools.javac.main.
+ * It should track changes made to that file.
+ */
+
+/**
+ * Various utility methods for processing Java tool command line arguments.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+class CommandLine {
+    /**
+     * Process Win32-style command files for the specified command line
+     * arguments and return the resulting arguments. A command file argument
+     * is of the form '@file' where 'file' is the name of the file whose
+     * contents are to be parsed for additional arguments. The contents of
+     * the command file are parsed using StreamTokenizer and the original
+     * '@file' argument replaced with the resulting tokens. Recursive command
+     * files are not supported. The '@' character itself can be quoted with
+     * the sequence '@@'.
+     * @param args the arguments that may contain @files
+     * @return the arguments, with @files expanded
+     * @throws IOException if there is a problem reading any of the @files
+     */
+    public static String[] parse(String[] args) throws IOException {
+        List<String> newArgs = new ArrayList<>();
+        appendParsedCommandArgs(newArgs, Arrays.asList(args));
+        return newArgs.toArray(new String[newArgs.size()]);
+    }
+
+    private static void appendParsedCommandArgs(List<String> newArgs,
+            List<String> args) throws IOException {
+        for (String arg : args) {
+            if (arg.length() > 1 && arg.charAt(0) == '@') {
+                arg = arg.substring(1);
+                if (arg.charAt(0) == '@') {
+                    newArgs.add(arg);
+                } else {
+                    loadCmdFile(arg, newArgs);
+                }
+            } else {
+                newArgs.add(arg);
+            }
+        }
+    }
+
+    private static void loadCmdFile(String name, List<String> args)
+            throws IOException {
+        if (!Files.isReadable(Path.of(name))) {
+            throw new FileNotFoundException(name);
+        }
+        try (Reader r = Files.newBufferedReader(Paths.get(name),
+                Charset.defaultCharset())) {
+            Tokenizer t = new Tokenizer(r);
+            String s;
+            while ((s = t.nextToken()) != null) {
+                args.add(s);
+            }
+        }
+    }
+
+    public static class Tokenizer {
+        private final Reader in;
+        private int ch;
+
+        public Tokenizer(Reader in) throws IOException {
+            this.in = in;
+            ch = in.read();
+        }
+
+        public String nextToken() throws IOException {
+            skipWhite();
+            if (ch == -1) {
+                return null;
+            }
+
+            StringBuilder sb = new StringBuilder();
+            char quoteChar = 0;
+
+            while (ch != -1) {
+                switch (ch) {
+                    case ' ':
+                    case '\t':
+                    case '\f':
+                        if (quoteChar == 0) {
+                            return sb.toString();
+                        }
+                        sb.append((char) ch);
+                        break;
+
+                    case '\n':
+                    case '\r':
+                        return sb.toString();
+
+                    case '\'':
+                    case '"':
+                        if (quoteChar == 0) {
+                            quoteChar = (char) ch;
+                        } else if (quoteChar == ch) {
+                            quoteChar = 0;
+                        } else {
+                            sb.append((char) ch);
+                        }
+                        break;
+
+                    case '\\':
+                        if (quoteChar != 0) {
+                            ch = in.read();
+                            switch (ch) {
+                                case '\n':
+                                case '\r':
+                                    while (ch == ' ' || ch == '\n'
+                                            || ch == '\r' || ch == '\t'
+                                            || ch == '\f') {
+                                        ch = in.read();
+                                    }
+                                    continue;
+
+                                case 'n':
+                                    ch = '\n';
+                                    break;
+                                case 'r':
+                                    ch = '\r';
+                                    break;
+                                case 't':
+                                    ch = '\t';
+                                    break;
+                                case 'f':
+                                    ch = '\f';
+                                    break;
+                            }
+                        }
+                        sb.append((char) ch);
+                        break;
+
+                    default:
+                        sb.append((char) ch);
+                }
+
+                ch = in.read();
+            }
+
+            return sb.toString();
+        }
+
+        void skipWhite() throws IOException {
+            while (ch != -1) {
+                switch (ch) {
+                    case ' ':
+                    case '\t':
+                    case '\n':
+                    case '\r':
+                    case '\f':
+                        break;
+
+                    case '#':
+                        ch = in.read();
+                        while (ch != '\n' && ch != '\r' && ch != -1) {
+                            ch = in.read();
+                        }
+                        break;
+
+                    default:
+                        return;
+                }
+
+                ch = in.read();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/main/Main.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2011, 2019, 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
+ * 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.incubator.jpackage.main;
+
+import jdk.incubator.jpackage.internal.Arguments;
+import jdk.incubator.jpackage.internal.Log;
+import jdk.incubator.jpackage.internal.CLIHelp;
+import java.io.PrintWriter;
+import java.util.ResourceBundle;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.text.MessageFormat;
+
+public class Main {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.MainResources");
+
+    /**
+     * main(String... args)
+     * This is the entry point for the jpackage tool.
+     *
+     * @param args command line arguments
+     */
+    public static void main(String... args) throws Exception {
+        // Create logger with default system.out and system.err
+        Log.setLogger(null);
+
+        int status = new jdk.incubator.jpackage.main.Main().execute(args);
+        System.exit(status);
+    }
+
+    /**
+     * execute() - this is the entry point for the ToolProvider API.
+     *
+     * @param out output stream
+     * @param err error output stream
+     * @param args command line arguments
+     * @return an exit code. 0 means success, non-zero means an error occurred.
+     */
+    public int execute(PrintWriter out, PrintWriter err, String... args) {
+        // Create logger with provided streams
+        Log.Logger logger = new Log.Logger();
+        logger.setPrintWriter(out, err);
+        Log.setLogger(logger);
+
+        return execute(args);
+    }
+
+    private int execute(String... args) {
+        try {
+            String[] newArgs;
+            try {
+                newArgs = CommandLine.parse(args);
+            } catch (FileNotFoundException fnfe) {
+                Log.error(MessageFormat.format(I18N.getString(
+                        "ERR_CannotParseOptions"), fnfe.getMessage()));
+                return 1;
+            } catch (IOException ioe) {
+                Log.error(ioe.getMessage());
+                return 1;
+            }
+
+            if (newArgs.length == 0) {
+                CLIHelp.showHelp(true);
+            } else if (hasHelp(newArgs)){
+                if (hasVersion(newArgs)) {
+                    Log.info(System.getProperty("java.version") + "\n");
+                }
+                CLIHelp.showHelp(false);
+            } else if (hasVersion(newArgs)) {
+                Log.info(System.getProperty("java.version"));
+            } else {
+                Arguments arguments = new Arguments(newArgs);
+                if (!arguments.processArguments()) {
+                    // processArguments() will log error message if failed.
+                    return 1;
+                }
+            }
+            return 0;
+        } finally {
+            Log.flush();
+        }
+    }
+
+    private boolean hasHelp(String[] args) {
+        for (String a : args) {
+            if ("--help".equals(a) || "-h".equals(a)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean hasVersion(String[] args) {
+        for (String a : args) {
+            if ("--version".equals(a)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/classes/module-info.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+
+/**
+ * Defines the Java Packaging tool, jpackage.
+ *
+ * <p>jpackage is a tool for generating self-contained application bundles.
+ *
+ * @moduleGraph
+ * @since 14
+ */
+
+module jdk.incubator.jpackage {
+    requires jdk.jlink;
+
+    requires java.desktop;
+
+    uses jdk.incubator.jpackage.internal.Bundler;
+    uses jdk.incubator.jpackage.internal.Bundlers;
+
+    provides jdk.incubator.jpackage.internal.Bundlers with
+        jdk.incubator.jpackage.internal.BasicBundlers;
+
+/*
+ * while jpackage is incubating, do not provide ToolProvider directly, but
+ * instead export jdk.incubator.jpackage.ToolProviderFactory
+ *
+ *    provides java.util.spi.ToolProvider
+ *        with jdk.incubator.jpackage.internal.JPackageToolProvider;
+ */
+    exports jdk.incubator.jpackage;
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/FileAttributes.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef FILEATTRIBUTES_H
+#define FILEATTRIBUTES_H
+
+#include "Platform.h"
+#include "PlatformString.h"
+#include "FileAttribute.h"
+
+#include <vector>
+
+class FileAttributes {
+private:
+    TString FFileName;
+    bool FFollowLink;
+    std::vector<FileAttribute> FAttributes;
+
+    bool WriteAttributes();
+    bool ReadAttributes();
+    bool Valid(const FileAttribute Value);
+
+public:
+    FileAttributes(const TString FileName, bool FollowLink = true);
+
+    void Append(const FileAttribute Value);
+    bool Contains(const FileAttribute Value);
+    void Remove(const FileAttribute Value);
+};
+
+#endif // FILEATTRIBUTES_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/FilePath.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef FILEPATH_H
+#define FILEPATH_H
+
+#include "Platform.h"
+#include "PlatformString.h"
+#include "FileAttribute.h"
+
+#include <vector>
+
+class FileAttributes {
+private:
+    TString FFileName;
+    bool FFollowLink;
+    std::vector<FileAttribute> FAttributes;
+
+    bool WriteAttributes();
+    bool ReadAttributes();
+    bool Valid(const FileAttribute Value);
+
+public:
+    FileAttributes(const TString FileName, bool FollowLink = true);
+
+    void Append(const FileAttribute Value);
+    bool Contains(const FileAttribute Value);
+    void Remove(const FileAttribute Value);
+};
+
+class FilePath {
+private:
+    FilePath(void) {}
+    ~FilePath(void) {}
+
+public:
+    static bool FileExists(const TString FileName);
+    static bool DirectoryExists(const TString DirectoryName);
+
+    static bool DeleteFile(const TString FileName);
+    static bool DeleteDirectory(const TString DirectoryName);
+
+    static TString ExtractFilePath(TString Path);
+    static TString ExtractFileExt(TString Path);
+    static TString ExtractFileName(TString Path);
+    static TString ChangeFileExt(TString Path, TString Extension);
+
+    static TString IncludeTrailingSeparator(const TString value);
+    static TString IncludeTrailingSeparator(const char* value);
+    static TString IncludeTrailingSeparator(const wchar_t* value);
+    static TString FixPathForPlatform(TString Path);
+    static TString FixPathSeparatorForPlatform(TString Path);
+    static TString PathSeparator();
+
+    static bool CreateDirectory(TString Path, bool ownerOnly);
+    static void ChangePermissions(TString FileName, bool ownerOnly);
+};
+
+#endif //FILEPATH_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Helpers.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "Helpers.h"
+#include "PlatformString.h"
+#include "PropertyFile.h"
+
+
+bool Helpers::SplitOptionIntoNameValue(
+        TString option, TString& Name, TString& Value) {
+    bool hasValue = false;
+    Name = _T("");
+    Value = _T("");
+    unsigned int index = 0;
+
+    for (; index < option.length(); index++) {
+        TCHAR c = option[index];
+
+        switch (c) {
+            case '=': {
+                index++;
+                hasValue = true;
+                break;
+            }
+
+            case '\\': {
+                if (index + 1 < option.length()) {
+                    c = option[index + 1];
+
+                    switch (c) {
+                        case '\\': {
+                            index++;
+                            Name += '\\';
+                            break;
+                        }
+
+                        case '=': {
+                            index++;
+                            Name += '=';
+                            break;
+                        }
+                    }
+
+                }
+
+                continue;
+            }
+
+            default: {
+                Name += c;
+                continue;
+            }
+        }
+
+        break;
+    }
+
+    if (hasValue) {
+        Value = option.substr(index, index - option.length());
+    }
+
+    return (option.length() > 0);
+}
+
+
+TString Helpers::ReplaceString(TString subject, const TString& search,
+                            const TString& replace) {
+    size_t pos = 0;
+    while((pos = subject.find(search, pos)) != TString::npos) {
+            subject.replace(pos, search.length(), replace);
+            pos += replace.length();
+    }
+    return subject;
+}
+
+TString Helpers::ConvertIdToFilePath(TString Value) {
+    TString search;
+    search = '.';
+    TString replace;
+    replace = '/';
+    TString result = ReplaceString(Value, search, replace);
+    return result;
+}
+
+TString Helpers::ConvertIdToJavaPath(TString Value) {
+    TString search;
+    search = '.';
+    TString replace;
+    replace = '/';
+    TString result = ReplaceString(Value, search, replace);
+    search = '\\';
+    result = ReplaceString(result, search, replace);
+    return result;
+}
+
+TString Helpers::ConvertJavaPathToId(TString Value) {
+    TString search;
+    search = '/';
+    TString replace;
+    replace = '.';
+    TString result = ReplaceString(Value, search, replace);
+    return result;
+}
+
+OrderedMap<TString, TString>
+        Helpers::GetJavaOptionsFromConfig(IPropertyContainer* config) {
+    OrderedMap<TString, TString> result;
+
+    for (unsigned int index = 0; index < config->GetCount(); index++) {
+        TString argname =
+                TString(_T("jvmarg.")) + PlatformString(index + 1).toString();
+        TString argvalue;
+
+        if (config->GetValue(argname, argvalue) == false) {
+            break;
+        }
+        else if (argvalue.empty() == false) {
+            TString name;
+            TString value;
+            if (Helpers::SplitOptionIntoNameValue(argvalue, name, value)) {
+                result.Append(name, value);
+            }
+        }
+    }
+
+    return result;
+}
+
+std::list<TString> Helpers::GetArgsFromConfig(IPropertyContainer* config) {
+    std::list<TString> result;
+
+    for (unsigned int index = 0; index < config->GetCount(); index++) {
+        TString argname = TString(_T("arg."))
+                + PlatformString(index + 1).toString();
+        TString argvalue;
+
+        if (config->GetValue(argname, argvalue) == false) {
+            break;
+        }
+        else if (argvalue.empty() == false) {
+            result.push_back((argvalue));
+        }
+    }
+
+    return result;
+}
+
+std::list<TString>
+        Helpers::MapToNameValueList(OrderedMap<TString, TString> Map) {
+    std::list<TString> result;
+    std::vector<TString> keys = Map.GetKeys();
+
+    for (OrderedMap<TString, TString>::const_iterator iterator = Map.begin();
+            iterator != Map.end(); iterator++) {
+       JPPair<TString, TString> *item = *iterator;
+       TString key = item->first;
+       TString value = item->second;
+
+       if (value.length() == 0) {
+           result.push_back(key);
+       } else {
+           result.push_back(key + _T('=') + value);
+        }
+    }
+
+    return result;
+}
+
+TString Helpers::NameValueToString(TString name, TString value) {
+    TString result;
+
+    if (value.empty() == true) {
+        result = name;
+    }
+    else {
+        result = name + TString(_T("=")) + value;
+    }
+
+    return result;
+}
+
+std::list<TString> Helpers::StringToArray(TString Value) {
+    std::list<TString> result;
+    TString line;
+
+    for (unsigned int index = 0; index < Value.length(); index++) {
+        TCHAR c = Value[index];
+
+        switch (c) {
+            case '\n': {
+                result.push_back(line);
+                line = _T("");
+                break;
+            }
+
+            case '\r': {
+                result.push_back(line);
+                line = _T("");
+
+                if (Value[index + 1] == '\n')
+                    index++;
+
+                break;
+            }
+
+            default: {
+                line += c;
+            }
+        }
+    }
+
+    // The buffer may not have ended with a Carriage Return/Line Feed.
+    if (line.length() > 0) {
+        result.push_back(line);
+    }
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Helpers.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef HELPERS_H
+#define HELPERS_H
+
+#include "Platform.h"
+#include "OrderedMap.h"
+#include "IniFile.h"
+
+
+class Helpers {
+private:
+    Helpers(void) {}
+    ~Helpers(void) {}
+
+public:
+    // Supports two formats for option:
+    // Example 1:
+    // foo=bar
+    //
+    // Example 2:
+    // <name=foo=, value=goo>
+    static bool SplitOptionIntoNameValue(TString option,
+            TString& Name, TString& Value);
+    static TString ReplaceString(TString subject, const TString& search,
+            const TString& replace);
+    static TString ConvertIdToFilePath(TString Value);
+    static TString ConvertIdToJavaPath(TString Value);
+    static TString ConvertJavaPathToId(TString Value);
+
+    static OrderedMap<TString, TString>
+            GetJavaOptionsFromConfig(IPropertyContainer* config);
+    static std::list<TString> GetArgsFromConfig(IPropertyContainer* config);
+
+    static std::list<TString>
+            MapToNameValueList(OrderedMap<TString, TString> Map);
+
+    static TString NameValueToString(TString name, TString value);
+
+    static std::list<TString> StringToArray(TString Value);
+};
+
+#endif // HELPERS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/IniFile.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2015, 2019, 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.
+ */
+
+#include "IniFile.h"
+#include "Helpers.h"
+
+#include <string>
+
+
+IniFile::IniFile() : ISectionalPropertyContainer() {
+}
+
+IniFile::~IniFile() {
+    for (OrderedMap<TString, IniSectionData*>::iterator iterator =
+            FMap.begin(); iterator != FMap.end(); iterator++) {
+        JPPair<TString, IniSectionData*> *item = *iterator;
+        delete item->second;
+    }
+}
+
+bool IniFile::LoadFromFile(const TString FileName) {
+    bool result = false;
+    Platform& platform = Platform::GetInstance();
+
+    std::list<TString> contents = platform.LoadFromFile(FileName);
+
+    if (contents.empty() == false) {
+        bool found = false;
+
+        // Determine the if file is an INI file or property file.
+        // Assign FDefaultSection if it is
+        // an INI file. Otherwise FDefaultSection is NULL.
+        for (std::list<TString>::const_iterator iterator = contents.begin();
+                iterator != contents.end(); iterator++) {
+            TString line = *iterator;
+
+            if (line[0] == ';') {
+                // Semicolon is a comment so ignore the line.
+                continue;
+            }
+            else {
+                if (line[0] == '[') {
+                    found = true;
+                }
+
+                break;
+            }
+        }
+
+        if (found == true) {
+            TString sectionName;
+
+            for (std::list<TString>::const_iterator iterator = contents.begin();
+                    iterator != contents.end(); iterator++) {
+                TString line = *iterator;
+
+                if (line[0] == ';') {
+                    // Semicolon is a comment so ignore the line.
+                    continue;
+                }
+                else if (line[0] == '[' && line[line.length() - 1] == ']') {
+                    sectionName = line.substr(1, line.size() - 2);
+                }
+                else if (sectionName.empty() == false) {
+                    TString name;
+                    TString value;
+
+                    if (Helpers::SplitOptionIntoNameValue(
+                            line, name, value) == true) {
+                        Append(sectionName, name, value);
+                    }
+                }
+            }
+
+            result = true;
+        }
+    }
+
+    return result;
+}
+
+bool IniFile::SaveToFile(const TString FileName, bool ownerOnly) {
+    bool result = false;
+
+    std::list<TString> contents;
+    std::vector<TString> keys = FMap.GetKeys();
+
+    for (unsigned int index = 0; index < keys.size(); index++) {
+        TString name = keys[index];
+        IniSectionData *section;
+
+        if (FMap.GetValue(name, section) == true) {
+            contents.push_back(_T("[") + name + _T("]"));
+            std::list<TString> lines = section->GetLines();
+            contents.insert(contents.end(), lines.begin(), lines.end());
+            contents.push_back(_T(""));
+        }
+    }
+
+    Platform& platform = Platform::GetInstance();
+    platform.SaveToFile(FileName, contents, ownerOnly);
+    result = true;
+    return result;
+}
+
+void IniFile::Append(const TString SectionName,
+        const TString Key, TString Value) {
+    if (FMap.ContainsKey(SectionName) == true) {
+        IniSectionData* section;
+
+        if (FMap.GetValue(SectionName, section) == true && section != NULL) {
+            section->SetValue(Key, Value);
+        }
+    }
+    else {
+        IniSectionData *section = new IniSectionData();
+        section->SetValue(Key, Value);
+        FMap.Append(SectionName, section);
+    }
+}
+
+void IniFile::AppendSection(const TString SectionName,
+        OrderedMap<TString, TString> Values) {
+    if (FMap.ContainsKey(SectionName) == true) {
+        IniSectionData* section;
+
+        if (FMap.GetValue(SectionName, section) == true && section != NULL) {
+            section->Append(Values);
+        }
+    }
+    else {
+        IniSectionData *section = new IniSectionData(Values);
+        FMap.Append(SectionName, section);
+    }
+}
+
+bool IniFile::GetValue(const TString SectionName,
+        const TString Key, TString& Value) {
+    bool result = false;
+    IniSectionData* section;
+
+    if (FMap.GetValue(SectionName, section) == true && section != NULL) {
+        result = section->GetValue(Key, Value);
+    }
+
+    return result;
+}
+
+bool IniFile::SetValue(const TString SectionName,
+        const TString Key, TString Value) {
+    bool result = false;
+    IniSectionData* section;
+
+    if (FMap.GetValue(SectionName, section) && section != NULL) {
+        result = section->SetValue(Key, Value);
+    }
+    else {
+        Append(SectionName, Key, Value);
+    }
+
+
+    return result;
+}
+
+bool IniFile::GetSection(const TString SectionName,
+        OrderedMap<TString, TString> &Data) {
+    bool result = false;
+
+    if (FMap.ContainsKey(SectionName) == true) {
+        IniSectionData* section = NULL;
+
+        if (FMap.GetValue(SectionName, section) == true && section != NULL) {
+            OrderedMap<TString, TString> data = section->GetData();
+            Data.Append(data);
+            result = true;
+        }
+    }
+
+    return result;
+}
+
+bool IniFile::ContainsSection(const TString SectionName) {
+    return FMap.ContainsKey(SectionName);
+}
+
+//----------------------------------------------------------------------------
+
+IniSectionData::IniSectionData() {
+    FMap.SetAllowDuplicates(true);
+}
+
+IniSectionData::IniSectionData(OrderedMap<TString, TString> Values) {
+    FMap = Values;
+}
+
+std::vector<TString> IniSectionData::GetKeys() {
+    return FMap.GetKeys();
+}
+
+std::list<TString> IniSectionData::GetLines() {
+    std::list<TString> result;
+    std::vector<TString> keys = FMap.GetKeys();
+
+    for (unsigned int index = 0; index < keys.size(); index++) {
+        TString name = keys[index];
+        TString value;
+
+        if (FMap.GetValue(name, value) == true) {
+            name = Helpers::ReplaceString(name, _T("="), _T("\\="));
+            value = Helpers::ReplaceString(value, _T("="), _T("\\="));
+
+            TString line = name + _T('=') + value;
+            result.push_back(line);
+        }
+    }
+
+    return result;
+}
+
+OrderedMap<TString, TString> IniSectionData::GetData() {
+    OrderedMap<TString, TString> result = FMap;
+    return result;
+}
+
+bool IniSectionData::GetValue(const TString Key, TString& Value) {
+    return FMap.GetValue(Key, Value);
+}
+
+bool IniSectionData::SetValue(const TString Key, TString Value) {
+    return FMap.SetValue(Key, Value);
+}
+
+void IniSectionData::Append(OrderedMap<TString, TString> Values) {
+    FMap.Append(Values);
+}
+
+size_t IniSectionData::GetCount() {
+    return FMap.Count();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/IniFile.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, 2019, 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.
+ */
+
+#ifndef INIFILE_H
+#define INIFILE_H
+
+#include "Platform.h"
+#include "OrderedMap.h"
+
+#include <map>
+
+
+class IniSectionData : public IPropertyContainer {
+private:
+    OrderedMap<TString, TString> FMap;
+
+public:
+    IniSectionData();
+    IniSectionData(OrderedMap<TString, TString> Values);
+
+    std::vector<TString> GetKeys();
+    std::list<TString> GetLines();
+    OrderedMap<TString, TString> GetData();
+
+    bool SetValue(const TString Key, TString Value);
+    void Append(OrderedMap<TString, TString> Values);
+
+    virtual bool GetValue(const TString Key, TString& Value);
+    virtual size_t GetCount();
+};
+
+
+class IniFile : public ISectionalPropertyContainer {
+private:
+    OrderedMap<TString, IniSectionData*> FMap;
+
+public:
+    IniFile();
+    virtual ~IniFile();
+
+    void internalTest();
+
+    bool LoadFromFile(const TString FileName);
+    bool SaveToFile(const TString FileName, bool ownerOnly = true);
+
+    void Append(const TString SectionName, const TString Key, TString Value);
+    void AppendSection(const TString SectionName,
+            OrderedMap<TString, TString> Values);
+    bool SetValue(const TString SectionName,
+            const TString Key, TString Value);
+
+    // ISectionalPropertyContainer
+    virtual bool GetSection(const TString SectionName,
+            OrderedMap<TString, TString> &Data);
+    virtual bool ContainsSection(const TString SectionName);
+    virtual bool GetValue(const TString SectionName,
+            const TString Key, TString& Value);
+};
+
+#endif // INIFILE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/JavaVirtualMachine.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "JavaVirtualMachine.h"
+#include "Platform.h"
+#include "PlatformString.h"
+#include "FilePath.h"
+#include "Package.h"
+#include "Helpers.h"
+#include "Messages.h"
+#include "Macros.h"
+
+#include "jni.h"
+
+#include <map>
+#include <list>
+#include <sstream>
+
+
+bool RunVM() {
+    JavaVirtualMachine javavm;
+
+    bool result = javavm.StartJVM();
+
+    if (!result) {
+        Platform& platform = Platform::GetInstance();
+        platform.ShowMessage(_T("Failed to launch JVM\n"));
+    }
+
+    return result;
+}
+
+//----------------------------------------------------------------------------
+
+JavaOptions::JavaOptions(): FOptions(NULL) {
+}
+
+JavaOptions::~JavaOptions() {
+    if (FOptions != NULL) {
+        for (unsigned int index = 0; index < GetCount(); index++) {
+            delete[] FOptions[index].optionString;
+        }
+
+        delete[] FOptions;
+    }
+}
+
+void JavaOptions::AppendValue(const TString Key, TString Value, void* Extra) {
+    JavaOptionItem item;
+    item.name = Key;
+    item.value = Value;
+    item.extraInfo = Extra;
+    FItems.push_back(item);
+}
+
+void JavaOptions::AppendValue(const TString Key, TString Value) {
+    AppendValue(Key, Value, NULL);
+}
+
+void JavaOptions::AppendValue(const TString Key) {
+    AppendValue(Key, _T(""), NULL);
+}
+
+void JavaOptions::AppendValues(OrderedMap<TString, TString> Values) {
+    if (Values.GetAllowDuplicates()) {
+        for (int i = 0; i < (int)Values.Count(); i++) {
+            TString name, value;
+
+            bool bResult = Values.GetKey(i, name);
+            bResult &= Values.GetValue(i, value);
+
+            if (bResult) {
+                AppendValue(name, value);
+            }
+        }
+    } else { // In case we asked to add values from OrderedMap with allow
+        // duplicates set to false. Not used now, but should avoid possible
+        // bugs.
+        std::vector<TString> orderedKeys = Values.GetKeys();
+
+        for (std::vector<TString>::const_iterator iterator = orderedKeys.begin();
+            iterator != orderedKeys.end(); iterator++) {
+            TString name = *iterator;
+            TString value;
+
+            if (Values.GetValue(name, value) == true) {
+                AppendValue(name, value);
+            }
+        }
+    }
+}
+
+void JavaOptions::ReplaceValue(const TString Key, TString Value) {
+    for (std::list<JavaOptionItem>::iterator iterator = FItems.begin();
+        iterator != FItems.end(); iterator++) {
+
+        TString lkey = iterator->name;
+
+        if (lkey == Key) {
+            JavaOptionItem item = *iterator;
+            item.value = Value;
+            iterator = FItems.erase(iterator);
+            FItems.insert(iterator, item);
+            break;
+        }
+    }
+}
+
+std::list<TString> JavaOptions::ToList() {
+    std::list<TString> result;
+    Macros& macros = Macros::GetInstance();
+
+    for (std::list<JavaOptionItem>::const_iterator iterator = FItems.begin();
+        iterator != FItems.end(); iterator++) {
+        TString key = iterator->name;
+        TString value = iterator->value;
+        TString option = Helpers::NameValueToString(key, value);
+        option = macros.ExpandMacros(option);
+        result.push_back(option);
+    }
+
+    return result;
+}
+
+size_t JavaOptions::GetCount() {
+    return FItems.size();
+}
+
+//----------------------------------------------------------------------------
+
+JavaVirtualMachine::JavaVirtualMachine() {
+}
+
+JavaVirtualMachine::~JavaVirtualMachine(void) {
+}
+
+bool JavaVirtualMachine::StartJVM() {
+    Platform& platform = Platform::GetInstance();
+    Package& package = Package::GetInstance();
+
+    TString classpath = package.GetClassPath();
+    TString modulepath = package.GetModulePath();
+    JavaOptions options;
+
+    if (modulepath.empty() == false) {
+        options.AppendValue(_T("-Djava.module.path"), modulepath);
+    }
+
+    options.AppendValue(_T("-Djava.library.path"),
+            package.GetPackageAppDirectory() + FilePath::PathSeparator()
+            + package.GetPackageLauncherDirectory());
+    options.AppendValue(
+            _T("-Djava.launcher.path"), package.GetPackageLauncherDirectory());
+    options.AppendValues(package.GetJavaOptions());
+
+#ifdef DEBUG
+    if (package.Debugging() == dsJava) {
+        options.AppendValue(_T("-Xdebug"), _T(""));
+        options.AppendValue(
+                _T("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=localhost:5005"),
+                _T(""));
+        platform.ShowMessage(_T("localhost:5005"));
+    }
+#endif // DEBUG
+
+    TString maxHeapSizeOption;
+    TString minHeapSizeOption;
+
+
+    if (package.GetMemoryState() == PackageBootFields::msAuto) {
+        TPlatformNumber memorySize = package.GetMemorySize();
+        TString memory =
+                PlatformString((size_t)memorySize).toString() + _T("m");
+        maxHeapSizeOption = TString(_T("-Xmx")) + memory;
+        options.AppendValue(maxHeapSizeOption, _T(""));
+
+        if (memorySize > 256)
+            minHeapSizeOption = _T("-Xms256m");
+        else
+            minHeapSizeOption = _T("-Xms") + memory;
+
+        options.AppendValue(minHeapSizeOption, _T(""));
+    }
+
+    TString mainClassName = package.GetMainClassName();
+    TString mainModule = package.GetMainModule();
+
+    if (mainClassName.empty() == true && mainModule.empty() == true) {
+        Messages& messages = Messages::GetInstance();
+        platform.ShowMessage(messages.GetMessage(NO_MAIN_CLASS_SPECIFIED));
+        return false;
+    }
+
+    configureLibrary();
+
+    // Initialize the arguments to JLI_Launch()
+    //
+    // On Mac OS X JLI_Launch spawns a new thread that actually starts the JVM.
+    // This new thread simply re-runs main(argc, argv). Therefore we do not
+    // want to add new args if we are still in the original main thread so we
+    // will treat them as command line args provided by the user ...
+    // Only propagate original set of args first time.
+
+    options.AppendValue(_T("-classpath"));
+    options.AppendValue(classpath);
+
+    std::list<TString> vmargs;
+    vmargs.push_back(package.GetCommandName());
+
+    if (package.HasSplashScreen() == true) {
+        options.AppendValue(TString(_T("-splash:"))
+                + package.GetSplashScreenFileName(), _T(""));
+    }
+
+    if (mainModule.empty() == true) {
+        options.AppendValue(Helpers::ConvertJavaPathToId(mainClassName),
+                _T(""));
+    } else {
+        options.AppendValue(_T("-m"));
+        options.AppendValue(mainModule);
+    }
+
+    return launchVM(options, vmargs);
+}
+
+void JavaVirtualMachine::configureLibrary() {
+    Platform& platform = Platform::GetInstance();
+    Package& package = Package::GetInstance();
+    TString libName = package.GetJavaLibraryFileName();
+    platform.addPlatformDependencies(&javaLibrary);
+    javaLibrary.Load(libName);
+}
+
+bool JavaVirtualMachine::launchVM(JavaOptions& options,
+        std::list<TString>& vmargs) {
+    Platform& platform = Platform::GetInstance();
+    Package& package = Package::GetInstance();
+
+#ifdef MAC
+    // Mac adds a ProcessSerialNumber to args when launched from .app
+    // filter out the psn since they it's not expected in the app
+    if (platform.IsMainThread() == false) {
+        std::list<TString> loptions = options.ToList();
+        vmargs.splice(vmargs.end(), loptions,
+                loptions.begin(), loptions.end());
+    }
+#else
+    std::list<TString> loptions = options.ToList();
+    vmargs.splice(vmargs.end(), loptions, loptions.begin(), loptions.end());
+#endif
+
+    std::list<TString> largs = package.GetArgs();
+    vmargs.splice(vmargs.end(), largs, largs.begin(), largs.end());
+
+    size_t argc = vmargs.size();
+    DynamicBuffer<char*> argv(argc + 1);
+    if (argv.GetData() == NULL) {
+        return false;
+    }
+
+    unsigned int index = 0;
+    for (std::list<TString>::const_iterator iterator = vmargs.begin();
+        iterator != vmargs.end(); iterator++) {
+        TString item = *iterator;
+        std::string arg = PlatformString(item).toStdString();
+#ifdef DEBUG
+        printf("%i %s\n", index, arg.c_str());
+#endif // DEBUG
+        argv[index] = PlatformString::duplicate(arg.c_str());
+        index++;
+    }
+
+    argv[argc] = NULL;
+
+// On Mac we can only free the boot fields if the calling thread is
+// not the main thread.
+#ifdef MAC
+    if (platform.IsMainThread() == false) {
+        package.FreeBootFields();
+    }
+#else
+    package.FreeBootFields();
+#endif // MAC
+
+    if (javaLibrary.JavaVMCreate(argc, argv.GetData()) == true) {
+        return true;
+    }
+
+    for (index = 0; index < argc; index++) {
+        if (argv[index] != NULL) {
+            delete[] argv[index];
+        }
+    }
+
+    return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/JavaVirtualMachine.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef JAVAVIRTUALMACHINE_H
+#define JAVAVIRTUALMACHINE_H
+
+
+#include "jni.h"
+#include "Platform.h"
+#include "Library.h"
+
+struct JavaOptionItem {
+    TString name;
+    TString value;
+    void* extraInfo;
+};
+
+class JavaOptions {
+private:
+    std::list<JavaOptionItem> FItems;
+    JavaVMOption* FOptions;
+
+public:
+    JavaOptions();
+    ~JavaOptions();
+
+    void AppendValue(const TString Key, TString Value, void* Extra);
+    void AppendValue(const TString Key, TString Value);
+    void AppendValue(const TString Key);
+    void AppendValues(OrderedMap<TString, TString> Values);
+    void ReplaceValue(const TString Key, TString Value);
+    std::list<TString> ToList();
+    size_t GetCount();
+};
+
+class JavaVirtualMachine {
+private:
+    JavaLibrary javaLibrary;
+
+    void configureLibrary();
+    bool launchVM(JavaOptions& options, std::list<TString>& vmargs);
+public:
+    JavaVirtualMachine();
+    ~JavaVirtualMachine(void);
+
+    bool StartJVM();
+};
+
+bool RunVM();
+
+#endif // JAVAVIRTUALMACHINE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Library.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "Library.h"
+#include "Platform.h"
+#include "Messages.h"
+#include "PlatformString.h"
+
+#include <fstream>
+#include <locale>
+
+Library::Library() {
+    Initialize();
+}
+
+Library::Library(const TString &FileName) {
+    Initialize();
+    Load(FileName);
+}
+
+Library::~Library() {
+    Unload();
+}
+
+void Library::Initialize() {
+    FModule = NULL;
+    FDependentLibraryNames = NULL;
+    FDependenciesLibraries = NULL;
+}
+
+void Library::InitializeDependencies() {
+    if (FDependentLibraryNames == NULL) {
+        FDependentLibraryNames = new std::vector<TString>();
+    }
+
+    if (FDependenciesLibraries == NULL) {
+        FDependenciesLibraries = new std::vector<Library*>();
+    }
+}
+
+void Library::LoadDependencies() {
+    if (FDependentLibraryNames != NULL && FDependenciesLibraries != NULL) {
+        for (std::vector<TString>::const_iterator iterator =
+                FDependentLibraryNames->begin();
+                iterator != FDependentLibraryNames->end(); iterator++) {
+            Library* library = new Library();
+
+            if (library->Load(*iterator) == true) {
+                FDependenciesLibraries->push_back(library);
+            }
+        }
+
+        delete FDependentLibraryNames;
+        FDependentLibraryNames = NULL;
+    }
+}
+
+void Library::UnloadDependencies() {
+    if (FDependenciesLibraries != NULL) {
+        for (std::vector<Library*>::const_iterator iterator =
+                FDependenciesLibraries->begin();
+                iterator != FDependenciesLibraries->end(); iterator++) {
+            Library* library = *iterator;
+
+            if (library != NULL) {
+                library->Unload();
+                delete library;
+            }
+        }
+
+        delete FDependenciesLibraries;
+        FDependenciesLibraries = NULL;
+    }
+}
+
+Procedure Library::GetProcAddress(const std::string& MethodName) const {
+    Platform& platform = Platform::GetInstance();
+    return platform.GetProcAddress(FModule, MethodName);
+}
+
+bool Library::Load(const TString &FileName) {
+    bool result = true;
+
+    if (FModule == NULL) {
+        LoadDependencies();
+        Platform& platform = Platform::GetInstance();
+        FModule = platform.LoadLibrary(FileName);
+
+        if (FModule == NULL) {
+            Messages& messages = Messages::GetInstance();
+            platform.ShowMessage(messages.GetMessage(LIBRARY_NOT_FOUND),
+                    FileName);
+            result = false;
+        } else {
+            fname = PlatformString(FileName).toStdString();
+        }
+    }
+
+    return result;
+}
+
+bool Library::Unload() {
+    bool result = false;
+
+    if (FModule != NULL) {
+        Platform& platform = Platform::GetInstance();
+        platform.FreeLibrary(FModule);
+        FModule = NULL;
+        UnloadDependencies();
+        result = true;
+    }
+
+    return result;
+}
+
+void Library::AddDependency(const TString &FileName) {
+    InitializeDependencies();
+
+    if (FDependentLibraryNames != NULL) {
+        FDependentLibraryNames->push_back(FileName);
+    }
+}
+
+void Library::AddDependencies(const std::vector<TString> &Dependencies) {
+    if (Dependencies.size() > 0) {
+        InitializeDependencies();
+
+        if (FDependentLibraryNames != NULL) {
+            for (std::vector<TString>::const_iterator iterator =
+                    FDependentLibraryNames->begin();
+                    iterator != FDependentLibraryNames->end(); iterator++) {
+                TString fileName = *iterator;
+                AddDependency(fileName);
+            }
+        }
+    }
+}
+
+JavaLibrary::JavaLibrary() : Library(), FCreateProc(NULL) {
+}
+
+bool JavaLibrary::JavaVMCreate(size_t argc, char *argv[]) {
+    if (FCreateProc == NULL) {
+        FCreateProc = (JAVA_CREATE) GetProcAddress(LAUNCH_FUNC);
+    }
+
+    if (FCreateProc == NULL) {
+        Platform& platform = Platform::GetInstance();
+        Messages& messages = Messages::GetInstance();
+        platform.ShowMessage(
+                messages.GetMessage(FAILED_LOCATING_JVM_ENTRY_POINT));
+        return false;
+    }
+
+    return FCreateProc((int) argc, argv,
+            0, NULL,
+            0, NULL,
+            "",
+            "",
+            "java",
+            "java",
+            false,
+            false,
+            false,
+            0) == 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Library.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef LIBRARY_H
+#define LIBRARY_H
+
+#include "PlatformDefs.h"
+//#include "Platform.h"
+#include "OrderedMap.h"
+
+#include "jni.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string>
+#include <map>
+#include <list>
+#include <vector>
+#include <fstream>
+
+using namespace std;
+
+// Private typedef for function pointer casting
+
+#if defined(_WIN32) && !defined(_WIN64)
+#define LAUNCH_FUNC "_JLI_Launch@56"
+#else
+#define LAUNCH_FUNC "JLI_Launch"
+#endif
+
+
+typedef int (JNICALL *JAVA_CREATE)(int argc, char ** argv,
+        int jargc, const char** jargv,
+        int appclassc, const char** appclassv,
+        const char* fullversion,
+        const char* dotversion,
+        const char* pname,
+        const char* lname,
+        jboolean javaargs,
+        jboolean cpwildcard,
+        jboolean javaw,
+        jint ergo);
+
+class Library {
+private:
+    std::vector<TString> *FDependentLibraryNames;
+    std::vector<Library*> *FDependenciesLibraries;
+    Module FModule;
+    std::string fname;
+
+    void Initialize();
+    void InitializeDependencies();
+    void LoadDependencies();
+    void UnloadDependencies();
+
+public:
+    void* GetProcAddress(const std::string& MethodName) const;
+
+public:
+    Library();
+    Library(const TString &FileName);
+    ~Library();
+
+    bool Load(const TString &FileName);
+    bool Unload();
+
+    const std::string& GetName() const {
+        return fname;
+    }
+
+    void AddDependency(const TString &FileName);
+    void AddDependencies(const std::vector<TString> &Dependencies);
+};
+
+class JavaLibrary : public Library {
+    JAVA_CREATE FCreateProc;
+    JavaLibrary(const TString &FileName);
+public:
+    JavaLibrary();
+    bool JavaVMCreate(size_t argc, char *argv[]);
+};
+
+#endif // LIBRARY_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Macros.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "Macros.h"
+#include "Package.h"
+#include "Helpers.h"
+
+
+Macros::Macros(void) {
+}
+
+Macros::~Macros(void) {
+}
+
+void Macros::Initialize() {
+    Package& package = Package::GetInstance();
+    Macros& macros = Macros::GetInstance();
+
+    // Public macros.
+    macros.AddMacro(_T("$ROOTDIR"), package.GetPackageRootDirectory());
+    macros.AddMacro(_T("$APPDIR"), package.GetPackageAppDirectory());
+    macros.AddMacro(_T("$BINDIR"), package.GetPackageLauncherDirectory());
+}
+
+Macros& Macros::GetInstance() {
+    static Macros instance;
+    return instance;
+}
+
+TString Macros::ExpandMacros(TString Value) {
+    TString result = Value;
+
+    for (std::map<TString, TString>::iterator iterator = FData.begin();
+        iterator != FData.end();
+        iterator++) {
+
+        TString name = iterator->first;
+
+        if (Value.find(name) != TString::npos) {
+            TString lvalue = iterator->second;
+            result = Helpers::ReplaceString(Value, name, lvalue);
+            result = ExpandMacros(result);
+            break;
+        }
+    }
+
+    return result;
+}
+
+void Macros::AddMacro(TString Key, TString Value) {
+    FData.insert(std::map<TString, TString>::value_type(Key, Value));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Macros.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef MACROS_H
+#define MACROS_H
+
+#include "Platform.h"
+
+#include <map>
+
+
+class Macros {
+private:
+    std::map<TString, TString> FData;
+
+    Macros(void);
+
+public:
+    static Macros& GetInstance();
+    static void Initialize();
+    ~Macros(void);
+
+    TString ExpandMacros(TString Value);
+    void AddMacro(TString Key, TString Value);
+};
+
+#endif // MACROS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Messages.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "Messages.h"
+#include "Platform.h"
+#include "FilePath.h"
+#include "Helpers.h"
+#include "Macros.h"
+#include "JavaVirtualMachine.h"
+
+Messages::Messages(void) {
+    FMessages.SetReadOnly(false);
+    FMessages.SetValue(LIBRARY_NOT_FOUND, _T("Failed to find library."));
+    FMessages.SetValue(FAILED_CREATING_JVM, _T("Failed to create JVM"));
+    FMessages.SetValue(FAILED_LOCATING_JVM_ENTRY_POINT,
+            _T("Failed to locate JLI_Launch"));
+    FMessages.SetValue(NO_MAIN_CLASS_SPECIFIED, _T("No main class specified"));
+    FMessages.SetValue(METHOD_NOT_FOUND, _T("No method %s in class %s."));
+    FMessages.SetValue(CLASS_NOT_FOUND, _T("Class %s not found."));
+    FMessages.SetValue(ERROR_INVOKING_METHOD, _T("Error invoking method."));
+    FMessages.SetValue(APPCDS_CACHE_FILE_NOT_FOUND,
+            _T("Error: AppCDS cache does not exists:\n%s\n"));
+}
+
+Messages& Messages::GetInstance() {
+    static Messages instance;
+    // Guaranteed to be destroyed. Instantiated on first use.
+    return instance;
+}
+
+Messages::~Messages(void) {
+}
+
+TString Messages::GetMessage(const TString Key) {
+    TString result;
+    FMessages.GetValue(Key, result);
+    Macros& macros = Macros::GetInstance();
+    result = macros.ExpandMacros(result);
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Messages.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef MESSAGES_H
+#define MESSAGES_H
+
+#include "PropertyFile.h"
+
+#define LIBRARY_NOT_FOUND _T("library.not.found")
+#define FAILED_CREATING_JVM _T("failed.creating.jvm")
+#define FAILED_LOCATING_JVM_ENTRY_POINT _T("failed.locating.jvm.entry.point")
+#define NO_MAIN_CLASS_SPECIFIED _T("no.main.class.specified")
+
+#define METHOD_NOT_FOUND _T("method.not.found")
+#define CLASS_NOT_FOUND _T("class.not.found")
+#define ERROR_INVOKING_METHOD _T("error.invoking.method")
+
+#define CONFIG_FILE_NOT_FOUND _T("config.file.not.found")
+
+#define BUNDLED_JVM_NOT_FOUND _T("bundled.jvm.not.found")
+
+#define APPCDS_CACHE_FILE_NOT_FOUND _T("appcds.cache.file.not.found")
+
+class Messages {
+private:
+    PropertyFile FMessages;
+
+    Messages(void);
+public:
+    static Messages& GetInstance();
+    ~Messages(void);
+
+    TString GetMessage(const TString Key);
+};
+
+#endif // MESSAGES_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/OrderedMap.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2015, 2019, 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.
+ */
+
+#ifndef ORDEREDMAP_H
+#define ORDEREDMAP_H
+
+#include <map>
+#include <vector>
+#include <assert.h>
+#include <stdexcept>
+
+#include <iostream>
+
+template <typename _T1, typename _T2>
+struct JPPair
+{
+    typedef _T1 first_type;
+    typedef _T2 second_type;
+
+    first_type first;
+    second_type second;
+
+    JPPair(first_type Value1, second_type Value2) {
+        first = Value1;
+        second = Value2;
+    }
+};
+
+
+template <typename TKey, typename TValue>
+class OrderedMap {
+public:
+    typedef TKey key_type;
+    typedef TValue mapped_type;
+    typedef JPPair<key_type, mapped_type> container_type;
+    typedef typename std::vector<container_type*>::iterator iterator;
+    typedef typename std::vector<container_type*>::const_iterator const_iterator;
+
+private:
+    typedef std::map<key_type, container_type*> map_type;
+    typedef std::vector<container_type*> list_type;
+
+    map_type FMap;
+    list_type FList;
+    bool FAllowDuplicates;
+
+    typename list_type::iterator FindListItem(const key_type Key) {
+        typename list_type::iterator result = FList.end();
+
+        for (typename list_type::iterator iterator =
+                FList.begin(); iterator != FList.end(); iterator++) {
+            container_type *item = *iterator;
+
+            if (item->first == Key) {
+                result = iterator;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+public:
+    OrderedMap() {
+        FAllowDuplicates = false;
+    }
+
+    OrderedMap(const OrderedMap<key_type, mapped_type> &Value) {
+        Append(Value);
+        FAllowDuplicates = Value.GetAllowDuplicates();
+    }
+
+    ~OrderedMap() {
+        Clear();
+    }
+
+    void SetAllowDuplicates(bool Value) {
+        FAllowDuplicates = Value;
+    }
+
+    bool GetAllowDuplicates() const {
+        return FAllowDuplicates;
+    }
+
+    iterator begin() {
+        return FList.begin();
+    }
+
+    const_iterator begin() const {
+        return FList.begin();
+    }
+
+    iterator end() {
+        return FList.end();
+    }
+
+    const_iterator end() const {
+        return FList.end();
+    }
+
+    void Clear() {
+        for (typename list_type::iterator iterator =
+                FList.begin(); iterator != FList.end(); iterator++) {
+            container_type *item = *iterator;
+
+            if (item != NULL) {
+                delete item;
+                item = NULL;
+            }
+        }
+
+        FMap.clear();
+        FList.clear();
+    }
+
+    bool ContainsKey(key_type Key) {
+        bool result = false;
+
+        if (FMap.find(Key) != FMap.end()) {
+            result = true;
+        }
+
+        return result;
+    }
+
+    std::vector<key_type> GetKeys() {
+        std::vector<key_type> result;
+
+        for (typename list_type::const_iterator iterator = FList.begin();
+             iterator != FList.end(); iterator++) {
+            container_type *item = *iterator;
+            result.push_back(item->first);
+        }
+
+        return result;
+    }
+
+    void Assign(const OrderedMap<key_type, mapped_type> &Value) {
+        Clear();
+        Append(Value);
+    }
+
+    void Append(const OrderedMap<key_type, mapped_type> &Value) {
+        for (size_t index = 0; index < Value.FList.size(); index++) {
+            container_type *item = Value.FList[index];
+            Append(item->first, item->second);
+        }
+    }
+
+    void Append(key_type Key, mapped_type Value) {
+        container_type *item = new container_type(Key, Value);
+        FMap.insert(std::pair<key_type, container_type*>(Key, item));
+        FList.push_back(item);
+    }
+
+    bool RemoveByKey(key_type Key) {
+        bool result = false;
+        typename list_type::iterator iterator = FindListItem(Key);
+
+        if (iterator != FList.end()) {
+            FMap.erase(Key);
+            FList.erase(iterator);
+            result = true;
+        }
+
+        return result;
+    }
+
+    bool GetValue(key_type Key, mapped_type &Value) {
+        bool result = false;
+        container_type* item = FMap[Key];
+
+        if (item != NULL) {
+            Value = item->second;
+            result = true;
+        }
+
+        return result;
+    }
+
+    bool SetValue(key_type Key, mapped_type &Value) {
+        bool result = false;
+
+        if ((FAllowDuplicates == false) && (ContainsKey(Key) == true)) {
+            container_type *item = FMap[Key];
+
+            if (item != NULL) {
+                item->second = Value;
+                result = true;
+            }
+        }
+        else {
+            Append(Key, Value);
+            result = true;
+        }
+
+        return result;
+    }
+
+    bool GetKey(int index, key_type &Value) {
+        if (index < 0 || index >= (int)FList.size()) {
+            return false;
+        }
+        container_type *item = FList.at(index);
+        if (item != NULL) {
+            Value = item->first;
+            return true;
+        }
+
+        return false;
+    }
+
+    bool GetValue(int index, mapped_type &Value) {
+        if (index < 0 || index >= (int)FList.size()) {
+            return false;
+        }
+        container_type *item = FList.at(index);
+        if (item != NULL) {
+            Value = item->second;
+            return true;
+        }
+
+        return false;
+    }
+
+    mapped_type &operator[](key_type Key) {
+        container_type* item = FMap[Key];
+        assert(item != NULL);
+
+        if (item != NULL) {
+            return item->second;
+        }
+
+        throw std::invalid_argument("Key not found");
+    }
+
+    OrderedMap& operator= (OrderedMap &Value) {
+        Clear();
+        FAllowDuplicates = Value.GetAllowDuplicates();
+        Append(Value);
+        return *this;
+    }
+
+    size_t Count() {
+        return FList.size();
+    }
+};
+
+#endif // ORDEREDMAP_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Package.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "Package.h"
+#include "Helpers.h"
+#include "Macros.h"
+#include "IniFile.h"
+
+#include <assert.h>
+
+
+Package::Package(void) {
+    FInitialized = false;
+    Initialize();
+}
+
+TPlatformNumber StringToPercentageOfNumber(TString Value,
+        TPlatformNumber Number) {
+    TPlatformNumber result = 0;
+    size_t percentage = atoi(PlatformString(Value.c_str()));
+
+    if (percentage > 0 && Number > 0) {
+        result = Number * percentage / 100;
+    }
+
+    return result;
+}
+
+void Package::Initialize() {
+    if (FInitialized == true) {
+        return;
+    }
+
+    Platform& platform = Platform::GetInstance();
+
+    FBootFields = new PackageBootFields();
+    FDebugging = dsNone;
+
+    // Allow duplicates for Java options, so we can have multiple --add-exports
+    // or similar args.
+    FBootFields->FJavaOptions.SetAllowDuplicates(true);
+    FBootFields->FPackageRootDirectory = platform.GetPackageRootDirectory();
+    FBootFields->FPackageAppDirectory = platform.GetPackageAppDirectory();
+    FBootFields->FPackageLauncherDirectory =
+            platform.GetPackageLauncherDirectory();
+    FBootFields->FAppDataDirectory = platform.GetAppDataDirectory();
+
+    std::map<TString, TString> keys = platform.GetKeys();
+
+    // Read from configure.cfg/Info.plist
+    AutoFreePtr<ISectionalPropertyContainer> config =
+            platform.GetConfigFile(platform.GetConfigFileName());
+
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+            keys[JPACKAGE_APP_DATA_DIR], FBootFields->FPackageAppDataDirectory);
+    FBootFields->FPackageAppDataDirectory =
+            FilePath::FixPathForPlatform(FBootFields->FPackageAppDataDirectory);
+
+    // Main JAR.
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+            keys[CONFIG_MAINJAR_KEY], FBootFields->FMainJar);
+    FBootFields->FMainJar = FilePath::FixPathForPlatform(FBootFields->FMainJar);
+
+    // Main Module.
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+            keys[CONFIG_MAINMODULE_KEY], FBootFields->FMainModule);
+
+    // Classpath.
+    // 1. If the provided class path contains main jar then only use
+    //    provided class path.
+    // 2. If class path provided by config file is empty then add main jar.
+    // 3. If main jar is not in provided class path then add it.
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+            keys[CONFIG_CLASSPATH_KEY], FBootFields->FClassPath);
+    FBootFields->FClassPath =
+            FilePath::FixPathSeparatorForPlatform(FBootFields->FClassPath);
+
+    if (FBootFields->FClassPath.empty() == true) {
+        FBootFields->FClassPath = GetMainJar();
+    } else if (FBootFields->FClassPath.find(GetMainJar()) == TString::npos) {
+        FBootFields->FClassPath = GetMainJar()
+                + FilePath::PathSeparator() + FBootFields->FClassPath;
+    }
+
+    // Modulepath.
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+            keys[CONFIG_MODULEPATH_KEY], FBootFields->FModulePath);
+    FBootFields->FModulePath =
+            FilePath::FixPathSeparatorForPlatform(FBootFields->FModulePath);
+
+    // Main Class.
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+            keys[CONFIG_MAINCLASSNAME_KEY], FBootFields->FMainClassName);
+
+    // Splash Screen.
+    if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+            keys[CONFIG_SPLASH_KEY],
+            FBootFields->FSplashScreenFileName) == true) {
+        FBootFields->FSplashScreenFileName =
+            FilePath::IncludeTrailingSeparator(GetPackageAppDirectory())
+            + FilePath::FixPathForPlatform(FBootFields->FSplashScreenFileName);
+
+        if (FilePath::FileExists(FBootFields->FSplashScreenFileName) == false) {
+            FBootFields->FSplashScreenFileName = _T("");
+        }
+    }
+
+    // Runtime.
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+            keys[JAVA_RUNTIME_KEY], FBootFields->FJavaRuntimeDirectory);
+
+    // Read jvmargs.
+    PromoteAppCDSState(config);
+    ReadJavaOptions(config);
+
+    // Read args if none were passed in.
+    if (FBootFields->FArgs.size() == 0) {
+        OrderedMap<TString, TString> args;
+
+        if (config->GetSection(keys[CONFIG_SECTION_ARGOPTIONS], args) == true) {
+            FBootFields->FArgs = Helpers::MapToNameValueList(args);
+        }
+    }
+
+    // Auto Memory.
+    TString autoMemory;
+
+    if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+            keys[CONFIG_APP_MEMORY], autoMemory) == true) {
+        if (autoMemory == _T("auto") || autoMemory == _T("100%")) {
+            FBootFields->FMemoryState = PackageBootFields::msAuto;
+            FBootFields->FMemorySize = platform.GetMemorySize();
+        } else if (autoMemory.length() == 2 && isdigit(autoMemory[0]) &&
+                autoMemory[1] == '%') {
+            FBootFields->FMemoryState = PackageBootFields::msAuto;
+            FBootFields->FMemorySize =
+                    StringToPercentageOfNumber(autoMemory.substr(0, 1),
+                    platform.GetMemorySize());
+        } else if (autoMemory.length() == 3 && isdigit(autoMemory[0]) &&
+                isdigit(autoMemory[1]) && autoMemory[2] == '%') {
+            FBootFields->FMemoryState = PackageBootFields::msAuto;
+            FBootFields->FMemorySize =
+                    StringToPercentageOfNumber(autoMemory.substr(0, 2),
+                    platform.GetMemorySize());
+        } else {
+            FBootFields->FMemoryState = PackageBootFields::msManual;
+            FBootFields->FMemorySize = 0;
+        }
+    }
+
+    // Debug
+    TString debug;
+    if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+            keys[CONFIG_APP_DEBUG], debug) == true) {
+        FBootFields->FArgs.push_back(debug);
+    }
+}
+
+void Package::Clear() {
+    FreeBootFields();
+    FInitialized = false;
+}
+
+// This is the only location that the AppCDS state should be modified except
+// by command line arguments provided by the user.
+//
+// The state of AppCDS is as follows:
+//
+// -> cdsUninitialized
+//    -> cdsGenCache If -Xappcds:generatecache
+//    -> cdsDisabled If -Xappcds:off
+//    -> cdsEnabled If "AppCDSJavaOptions" section is present
+//    -> cdsAuto If "AppCDSJavaOptions" section is present and
+//               app.appcds.cache=auto
+//    -> cdsDisabled Default
+//
+void Package::PromoteAppCDSState(ISectionalPropertyContainer* Config) {
+    Platform& platform = Platform::GetInstance();
+    std::map<TString, TString> keys = platform.GetKeys();
+
+    // The AppCDS state can change at this point.
+    switch (platform.GetAppCDSState()) {
+        case cdsEnabled:
+        case cdsAuto:
+        case cdsDisabled:
+        case cdsGenCache: {
+            // Do nothing.
+            break;
+        }
+
+        case cdsUninitialized: {
+            if (Config->ContainsSection(
+                    keys[CONFIG_SECTION_APPCDSJAVAOPTIONS]) == true) {
+                // If the AppCDS section is present then enable AppCDS.
+                TString appCDSCacheValue;
+
+                // If running with AppCDS enabled, and the configuration has
+                // been setup so "auto" is enabled, then
+                // the launcher will attempt to generate the cache file
+                // automatically and run the application.
+                if (Config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+                        _T("app.appcds.cache"), appCDSCacheValue) == true &&
+                    appCDSCacheValue == _T("auto")) {
+                    platform.SetAppCDSState(cdsAuto);
+                }
+                else {
+                    platform.SetAppCDSState(cdsEnabled);
+                }
+            } else {
+
+                platform.SetAppCDSState(cdsDisabled);
+            }
+        }
+    }
+}
+
+void Package::ReadJavaOptions(ISectionalPropertyContainer* Config) {
+    Platform& platform = Platform::GetInstance();
+    std::map<TString, TString> keys = platform.GetKeys();
+
+    // Evaluate based on the current AppCDS state.
+    switch (platform.GetAppCDSState()) {
+        case cdsUninitialized: {
+            throw Exception(_T("Internal Error"));
+        }
+
+        case cdsDisabled: {
+            Config->GetSection(keys[CONFIG_SECTION_JAVAOPTIONS],
+                    FBootFields->FJavaOptions);
+            break;
+        }
+
+        case cdsGenCache: {
+            Config->GetSection(keys[
+                    CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS],
+                    FBootFields->FJavaOptions);
+            break;
+        }
+
+        case cdsAuto:
+        case cdsEnabled: {
+            if (Config->GetValue(keys[CONFIG_SECTION_APPCDSJAVAOPTIONS],
+                    _T( "-XX:SharedArchiveFile"),
+                    FBootFields->FAppCDSCacheFileName) == true) {
+                // File names may contain the incorrect path separators.
+                // The cache file name must be corrected at this point.
+                if (FBootFields->FAppCDSCacheFileName.empty() == false) {
+                    IniFile* iniConfig = dynamic_cast<IniFile*>(Config);
+
+                    if (iniConfig != NULL) {
+                        FBootFields->FAppCDSCacheFileName =
+                                FilePath::FixPathForPlatform(
+                                FBootFields->FAppCDSCacheFileName);
+                        iniConfig->SetValue(keys[
+                                CONFIG_SECTION_APPCDSJAVAOPTIONS],
+                                _T( "-XX:SharedArchiveFile"),
+                                FBootFields->FAppCDSCacheFileName);
+                    }
+                }
+
+                Config->GetSection(keys[CONFIG_SECTION_APPCDSJAVAOPTIONS],
+                        FBootFields->FJavaOptions);
+            }
+
+            break;
+        }
+    }
+}
+
+void Package::SetCommandLineArguments(int argc, TCHAR* argv[]) {
+    if (argc > 0) {
+        std::list<TString> args;
+
+        // Prepare app arguments. Skip value at index 0 -
+        // this is path to executable.
+        FBootFields->FCommandName = argv[0];
+
+        // Path to executable is at 0 index so start at index 1.
+        for (int index = 1; index < argc; index++) {
+            TString arg = argv[index];
+
+#ifdef DEBUG
+            if (arg == _T("-debug")) {
+                FDebugging = dsNative;
+            }
+
+            if (arg == _T("-javadebug")) {
+                FDebugging = dsJava;
+            }
+#endif //DEBUG
+#ifdef MAC
+            if (arg.find(_T("-psn_"), 0) != TString::npos) {
+                Platform& platform = Platform::GetInstance();
+
+                if (platform.IsMainThread() == true) {
+#ifdef DEBUG
+                    printf("%s\n", arg.c_str());
+#endif //DEBUG
+                    continue;
+                }
+            }
+
+            if (arg == _T("-NSDocumentRevisionsDebugMode")) {
+                // Ignore -NSDocumentRevisionsDebugMode and
+                // the following YES/NO
+                index++;
+                continue;
+            }
+#endif //MAC
+
+            args.push_back(arg);
+        }
+
+        if (args.size() > 0) {
+            FBootFields->FArgs = args;
+        }
+    }
+}
+
+Package& Package::GetInstance() {
+    static Package instance;
+    // Guaranteed to be destroyed. Instantiated on first use.
+    return instance;
+}
+
+Package::~Package(void) {
+    FreeBootFields();
+}
+
+void Package::FreeBootFields() {
+    if (FBootFields != NULL) {
+        delete FBootFields;
+        FBootFields = NULL;
+    }
+}
+
+OrderedMap<TString, TString> Package::GetJavaOptions() {
+    return FBootFields->FJavaOptions;
+}
+
+std::vector<TString> GetKeysThatAreNotDuplicates(OrderedMap<TString,
+        TString> &Defaults, OrderedMap<TString, TString> &Overrides) {
+    std::vector<TString> result;
+    std::vector<TString> overrideKeys = Overrides.GetKeys();
+
+    for (size_t index = 0; index < overrideKeys.size(); index++) {
+        TString overridesKey = overrideKeys[index];
+        TString overridesValue;
+        TString defaultValue;
+
+        if ((Defaults.ContainsKey(overridesKey) == false) ||
+           (Defaults.GetValue(overridesKey, defaultValue) == true &&
+            Overrides.GetValue(overridesKey, overridesValue) == true &&
+            defaultValue != overridesValue)) {
+            result.push_back(overridesKey);
+        }
+    }
+
+    return result;
+}
+
+OrderedMap<TString, TString> CreateOrderedMapFromKeyList(OrderedMap<TString,
+        TString> &Map, std::vector<TString> &Keys) {
+    OrderedMap<TString, TString> result;
+
+    for (size_t index = 0; index < Keys.size(); index++) {
+        TString key = Keys[index];
+        TString value;
+
+        if (Map.GetValue(key, value) == true) {
+            result.Append(key, value);
+        }
+    }
+
+    return result;
+}
+
+std::vector<TString> GetKeysThatAreNotOverridesOfDefaultValues(
+        OrderedMap<TString, TString> &Defaults, OrderedMap<TString,
+        TString> &Overrides) {
+    std::vector<TString> result;
+    std::vector<TString> keys = Overrides.GetKeys();
+
+    for (unsigned int index = 0; index< keys.size(); index++) {
+        TString key = keys[index];
+
+        if (Defaults.ContainsKey(key) == true) {
+            try {
+                TString value = Overrides[key];
+                Defaults[key] = value;
+            }
+            catch (std::out_of_range &) {
+            }
+        }
+        else {
+            result.push_back(key);
+        }
+    }
+
+    return result;
+}
+
+std::list<TString> Package::GetArgs() {
+    assert(FBootFields != NULL);
+    return FBootFields->FArgs;
+}
+
+TString Package::GetPackageRootDirectory() {
+    assert(FBootFields != NULL);
+    return FBootFields->FPackageRootDirectory;
+}
+
+TString Package::GetPackageAppDirectory() {
+    assert(FBootFields != NULL);
+    return FBootFields->FPackageAppDirectory;
+}
+
+TString Package::GetPackageLauncherDirectory() {
+    assert(FBootFields != NULL);
+    return FBootFields->FPackageLauncherDirectory;
+}
+
+TString Package::GetAppDataDirectory() {
+    assert(FBootFields != NULL);
+    return FBootFields->FAppDataDirectory;
+}
+
+TString Package::GetAppCDSCacheDirectory() {
+    if (FAppCDSCacheDirectory.empty()) {
+        Platform& platform = Platform::GetInstance();
+        FAppCDSCacheDirectory = FilePath::IncludeTrailingSeparator(
+                platform.GetAppDataDirectory())
+                + FilePath::IncludeTrailingSeparator(
+                GetPackageAppDataDirectory()) + _T("cache");
+
+        Macros& macros = Macros::GetInstance();
+        FAppCDSCacheDirectory = macros.ExpandMacros(FAppCDSCacheDirectory);
+        FAppCDSCacheDirectory =
+                FilePath::FixPathForPlatform(FAppCDSCacheDirectory);
+    }
+
+    return FAppCDSCacheDirectory;
+}
+
+TString Package::GetAppCDSCacheFileName() {
+    assert(FBootFields != NULL);
+
+    if (FBootFields->FAppCDSCacheFileName.empty() == false) {
+        Macros& macros = Macros::GetInstance();
+        FBootFields->FAppCDSCacheFileName =
+                macros.ExpandMacros(FBootFields->FAppCDSCacheFileName);
+        FBootFields->FAppCDSCacheFileName =
+                FilePath::FixPathForPlatform(FBootFields->FAppCDSCacheFileName);
+    }
+
+    return FBootFields->FAppCDSCacheFileName;
+}
+
+TString Package::GetPackageAppDataDirectory() {
+    assert(FBootFields != NULL);
+    return FBootFields->FPackageAppDataDirectory;
+}
+
+TString Package::GetClassPath() {
+    assert(FBootFields != NULL);
+    return FBootFields->FClassPath;
+}
+
+TString Package::GetModulePath() {
+    assert(FBootFields != NULL);
+    return FBootFields->FModulePath;
+}
+
+TString Package::GetMainJar() {
+    assert(FBootFields != NULL);
+    return FBootFields->FMainJar;
+}
+
+TString Package::GetMainModule() {
+    assert(FBootFields != NULL);
+    return FBootFields->FMainModule;
+}
+
+TString Package::GetMainClassName() {
+    assert(FBootFields != NULL);
+    return FBootFields->FMainClassName;
+}
+
+TString Package::GetJavaLibraryFileName() {
+    assert(FBootFields != NULL);
+
+    if (FBootFields->FJavaLibraryFileName.empty() == true) {
+        Platform& platform = Platform::GetInstance();
+        Macros& macros = Macros::GetInstance();
+        TString jvmRuntimePath = macros.ExpandMacros(GetJavaRuntimeDirectory());
+        FBootFields->FJavaLibraryFileName =
+                platform.GetBundledJavaLibraryFileName(jvmRuntimePath);
+    }
+
+    return FBootFields->FJavaLibraryFileName;
+}
+
+TString Package::GetJavaRuntimeDirectory() {
+    assert(FBootFields != NULL);
+    return FBootFields->FJavaRuntimeDirectory;
+}
+
+TString Package::GetSplashScreenFileName() {
+    assert(FBootFields != NULL);
+    return FBootFields->FSplashScreenFileName;
+}
+
+bool Package::HasSplashScreen() {
+    assert(FBootFields != NULL);
+    return FilePath::FileExists(FBootFields->FSplashScreenFileName);
+}
+
+TString Package::GetCommandName() {
+    assert(FBootFields != NULL);
+    return FBootFields->FCommandName;
+}
+
+TPlatformNumber Package::GetMemorySize() {
+    assert(FBootFields != NULL);
+    return FBootFields->FMemorySize;
+}
+
+PackageBootFields::MemoryState Package::GetMemoryState() {
+    assert(FBootFields != NULL);
+    return FBootFields->FMemoryState;
+}
+
+DebugState Package::Debugging() {
+    return FDebugging;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Package.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef PACKAGE_H
+#define PACKAGE_H
+
+
+#include "Platform.h"
+#include "PlatformString.h"
+#include "FilePath.h"
+#include "PropertyFile.h"
+
+#include <map>
+#include <list>
+
+class PackageBootFields {
+public:
+    enum MemoryState {msManual, msAuto};
+
+public:
+    OrderedMap<TString, TString> FJavaOptions;
+    std::list<TString> FArgs;
+
+    TString FPackageRootDirectory;
+    TString FPackageAppDirectory;
+    TString FPackageLauncherDirectory;
+    TString FAppDataDirectory;
+    TString FPackageAppDataDirectory;
+    TString FClassPath;
+    TString FModulePath;
+    TString FMainJar;
+    TString FMainModule;
+    TString FMainClassName;
+    TString FJavaRuntimeDirectory;
+    TString FJavaLibraryFileName;
+    TString FSplashScreenFileName;
+    bool FUseJavaPreferences;
+    TString FCommandName;
+
+    TString FAppCDSCacheFileName;
+
+    TPlatformNumber FMemorySize;
+    MemoryState FMemoryState;
+};
+
+
+class Package {
+private:
+    Package(Package const&); // Don't Implement.
+    void operator=(Package const&); // Don't implement
+
+private:
+    bool FInitialized;
+    PackageBootFields* FBootFields;
+    TString FAppCDSCacheDirectory;
+
+    DebugState FDebugging;
+
+    Package(void);
+
+    TString GetMainJar();
+    void ReadJavaOptions(ISectionalPropertyContainer* Config);
+    void PromoteAppCDSState(ISectionalPropertyContainer* Config);
+
+public:
+    static Package& GetInstance();
+    ~Package(void);
+
+    void Initialize();
+    void Clear();
+    void FreeBootFields();
+
+    void SetCommandLineArguments(int argc, TCHAR* argv[]);
+
+    OrderedMap<TString, TString> GetJavaOptions();
+    TString GetMainModule();
+
+    std::list<TString> GetArgs();
+
+    TString GetPackageRootDirectory();
+    TString GetPackageAppDirectory();
+    TString GetPackageLauncherDirectory();
+    TString GetAppDataDirectory();
+
+    TString GetAppCDSCacheDirectory();
+    TString GetAppCDSCacheFileName();
+
+    TString GetPackageAppDataDirectory();
+    TString GetClassPath();
+    TString GetModulePath();
+    TString GetMainClassName();
+    TString GetJavaLibraryFileName();
+    TString GetJavaRuntimeDirectory();
+    TString GetSplashScreenFileName();
+    bool HasSplashScreen();
+    TString GetCommandName();
+
+    TPlatformNumber GetMemorySize();
+    PackageBootFields::MemoryState GetMemoryState();
+
+    DebugState Debugging();
+};
+
+#endif // PACKAGE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Platform.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "Platform.h"
+#include "Messages.h"
+#include "PlatformString.h"
+#include "FilePath.h"
+
+#include <fstream>
+#include <locale>
+
+#ifdef WINDOWS
+#include "WindowsPlatform.h"
+#endif // WINDOWS
+#ifdef LINUX
+#include "LinuxPlatform.h"
+#endif // LINUX
+#ifdef MAC
+#include "MacPlatform.h"
+#endif // MAC
+
+Platform& Platform::GetInstance() {
+#ifdef WINDOWS
+    static WindowsPlatform instance;
+#endif // WINDOWS
+
+#ifdef LINUX
+    static LinuxPlatform instance;
+#endif // LINUX
+
+#ifdef MAC
+    static MacPlatform instance;
+#endif // MAC
+
+    return instance;
+}
+
+TString Platform::GetConfigFileName() {
+    TString result;
+    TString basedir = GetPackageAppDirectory();
+
+    if (basedir.empty() == false) {
+        basedir = FilePath::IncludeTrailingSeparator(basedir);
+        TString appConfig = basedir + GetAppName() + _T(".cfg");
+
+        if (FilePath::FileExists(appConfig) == true) {
+            result = appConfig;
+        }
+        else {
+            result = basedir + _T("package.cfg");
+
+            if (FilePath::FileExists(result) == false) {
+                result = _T("");
+            }
+        }
+    }
+
+    return result;
+}
+
+std::list<TString> Platform::LoadFromFile(TString FileName) {
+    std::list<TString> result;
+
+    if (FilePath::FileExists(FileName) == true) {
+        std::wifstream stream(FileName.data());
+        InitStreamLocale(&stream);
+
+        if (stream.is_open() == true) {
+            while (stream.eof() == false) {
+                std::wstring line;
+                std::getline(stream, line);
+
+                // # at the first character will comment out the line.
+                if (line.empty() == false && line[0] != '#') {
+                    result.push_back(PlatformString(line).toString());
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+void Platform::SaveToFile(TString FileName, std::list<TString> Contents, bool ownerOnly) {
+    TString path = FilePath::ExtractFilePath(FileName);
+
+    if (FilePath::DirectoryExists(path) == false) {
+        FilePath::CreateDirectory(path, ownerOnly);
+    }
+
+    std::wofstream stream(FileName.data());
+    InitStreamLocale(&stream);
+
+    FilePath::ChangePermissions(FileName.data(), ownerOnly);
+
+    if (stream.is_open() == true) {
+        for (std::list<TString>::const_iterator iterator =
+                Contents.begin(); iterator != Contents.end(); iterator++) {
+            TString line = *iterator;
+            stream << PlatformString(line).toUnicodeString() << std::endl;
+        }
+    }
+}
+
+std::map<TString, TString> Platform::GetKeys() {
+    std::map<TString, TString> keys;
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_VERSION,
+            _T("app.version")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINJAR_KEY,
+            _T("app.mainjar")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINMODULE_KEY,
+            _T("app.mainmodule")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINCLASSNAME_KEY,
+            _T("app.mainclass")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_CLASSPATH_KEY,
+            _T("app.classpath")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_MODULEPATH_KEY,
+            _T("app.modulepath")));
+    keys.insert(std::map<TString, TString>::value_type(APP_NAME_KEY,
+            _T("app.name")));
+    keys.insert(std::map<TString, TString>::value_type(JAVA_RUNTIME_KEY,
+            _T("app.runtime")));
+    keys.insert(std::map<TString, TString>::value_type(JPACKAGE_APP_DATA_DIR,
+            _T("app.identifier")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_SPLASH_KEY,
+            _T("app.splash")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_MEMORY,
+            _T("app.memory")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_DEBUG,
+            _T("app.debug")));
+    keys.insert(std::map<TString,
+            TString>::value_type(CONFIG_APPLICATION_INSTANCE,
+            _T("app.application.instance")));
+    keys.insert(std::map<TString,
+            TString>::value_type(CONFIG_SECTION_APPLICATION,
+            _T("Application")));
+    keys.insert(std::map<TString,
+            TString>::value_type(CONFIG_SECTION_JAVAOPTIONS,
+            _T("JavaOptions")));
+    keys.insert(std::map<TString,
+            TString>::value_type(CONFIG_SECTION_APPCDSJAVAOPTIONS,
+            _T("AppCDSJavaOptions")));
+    keys.insert(std::map<TString,
+            TString>::value_type(CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS,
+            _T("AppCDSGenerateCacheJavaOptions")));
+    keys.insert(std::map<TString,
+            TString>::value_type(CONFIG_SECTION_ARGOPTIONS,
+            _T("ArgOptions")));
+
+    return keys;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Platform.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+#include "PlatformDefs.h"
+#include "Properties.h"
+#include "OrderedMap.h"
+#include "Library.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string>
+#include <map>
+#include <list>
+#include <vector>
+#include <fstream>
+
+using namespace std;
+
+// Config file sections
+#define CONFIG_SECTION_APPLICATION        _T("CONFIG_SECTION_APPLICATION")
+#define CONFIG_SECTION_JAVAOPTIONS        _T("CONFIG_SECTION_JAVAOPTIONS")
+#define CONFIG_SECTION_APPCDSJAVAOPTIONS  _T("CONFIG_SECTION_APPCDSJAVAOPTIONS")
+#define CONFIG_SECTION_ARGOPTIONS         _T("CONFIG_SECTION_ARGOPTIONS")
+#define CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS \
+        _T("CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS")
+
+// Config file keys.
+#define CONFIG_VERSION            _T("CONFIG_VERSION")
+#define CONFIG_MAINJAR_KEY        _T("CONFIG_MAINJAR_KEY")
+#define CONFIG_MAINMODULE_KEY     _T("CONFIG_MAINMODULE_KEY")
+#define CONFIG_MAINCLASSNAME_KEY  _T("CONFIG_MAINCLASSNAME_KEY")
+#define CONFIG_CLASSPATH_KEY      _T("CONFIG_CLASSPATH_KEY")
+#define CONFIG_MODULEPATH_KEY     _T("CONFIG_MODULEPATH_KEY")
+#define APP_NAME_KEY              _T("APP_NAME_KEY")
+#define CONFIG_SPLASH_KEY         _T("CONFIG_SPLASH_KEY")
+#define CONFIG_APP_MEMORY         _T("CONFIG_APP_MEMORY")
+#define CONFIG_APP_DEBUG          _T("CONFIG_APP_DEBUG")
+#define CONFIG_APPLICATION_INSTANCE _T("CONFIG_APPLICATION_INSTANCE")
+
+#define JAVA_RUNTIME_KEY           _T("JAVA_RUNTIME_KEY")
+#define JPACKAGE_APP_DATA_DIR     _T("CONFIG_APP_IDENTIFIER")
+
+struct WideString {
+    size_t length;
+    wchar_t* data;
+
+    WideString() { length = 0; data = NULL; }
+};
+
+struct MultibyteString {
+    size_t length;
+    char* data;
+
+    MultibyteString() { length = 0; data = NULL; }
+};
+
+class Process {
+protected:
+    std::list<TString> FOutput;
+
+public:
+    Process() {
+        Output.SetInstance(this);
+        Input.SetInstance(this);
+    }
+
+    virtual ~Process() {}
+
+    virtual bool IsRunning() = 0;
+    virtual bool Terminate() = 0;
+    virtual bool Execute(const TString Application,
+        const std::vector<TString> Arguments, bool AWait = false) = 0;
+    virtual bool Wait() = 0;
+    virtual TProcessID GetProcessID() = 0;
+
+    virtual std::list<TString> GetOutput() { return FOutput; }
+    virtual void SetInput(TString Value) = 0;
+
+    ReadProperty<Process, std::list<TString>, &Process::GetOutput> Output;
+    WriteProperty<Process, TString, &Process::SetInput> Input;
+};
+
+
+template <typename T>
+class AutoFreePtr {
+private:
+    T* FObject;
+
+public:
+    AutoFreePtr() {
+        FObject = NULL;
+    }
+
+    AutoFreePtr(T* Value) {
+        FObject = Value;
+    }
+
+    ~AutoFreePtr() {
+        if (FObject != NULL) {
+            delete FObject;
+        }
+    }
+
+    operator T* () const {
+        return FObject;
+    }
+
+    T& operator* () const {
+        return *FObject;
+    }
+
+    T* operator->() const {
+        return FObject;
+    }
+
+    T** operator&() {
+        return &FObject;
+    }
+
+    T* operator=(const T * rhs) {
+        FObject = rhs;
+        return FObject;
+    }
+};
+
+enum DebugState {dsNone, dsNative, dsJava};
+enum MessageResponse {mrOK, mrCancel};
+enum AppCDSState {cdsUninitialized, cdsDisabled,
+        cdsEnabled, cdsAuto, cdsGenCache};
+
+class Platform {
+private:
+    AppCDSState FAppCDSState;
+
+protected:
+    Platform(void): FAppCDSState(cdsUninitialized) {
+    }
+
+public:
+    AppCDSState GetAppCDSState() { return FAppCDSState; }
+    void SetAppCDSState(AppCDSState Value) { FAppCDSState = Value; }
+
+    static Platform& GetInstance();
+
+    virtual ~Platform(void) {}
+
+public:
+    virtual void ShowMessage(TString title, TString description) = 0;
+    virtual void ShowMessage(TString description) = 0;
+    virtual MessageResponse ShowResponseMessage(TString title,
+           TString description) = 0;
+
+    // Caller must free result using delete[].
+    virtual TCHAR* ConvertStringToFileSystemString(TCHAR* Source,
+            bool &release) = 0;
+
+    // Caller must free result using delete[].
+    virtual TCHAR* ConvertFileSystemStringToString(TCHAR* Source,
+            bool &release) = 0;
+
+    // Returns:
+    // Windows=C:\Users\<username>\AppData\Local
+    // Linux=~/.local
+    // Mac=~/Library/Application Support
+    virtual TString GetAppDataDirectory() = 0;
+
+    virtual TString GetPackageAppDirectory() = 0;
+    virtual TString GetPackageLauncherDirectory() = 0;
+    virtual TString GetPackageRuntimeBinDirectory() = 0;
+    virtual TString GetAppName() = 0;
+
+    virtual TString GetConfigFileName();
+
+    virtual TString GetBundledJavaLibraryFileName(TString RuntimePath) = 0;
+
+    // Caller must free result.
+    virtual ISectionalPropertyContainer* GetConfigFile(TString FileName) = 0;
+
+    virtual TString GetModuleFileName() = 0;
+    virtual TString GetPackageRootDirectory() = 0;
+
+    virtual Module LoadLibrary(TString FileName) = 0;
+    virtual void FreeLibrary(Module Module) = 0;
+    virtual Procedure GetProcAddress(Module Module, std::string MethodName) = 0;
+
+    // Caller must free result.
+    virtual Process* CreateProcess() = 0;
+
+    virtual bool IsMainThread() = 0;
+
+    // Returns megabytes.
+    virtual TPlatformNumber GetMemorySize() = 0;
+
+    virtual std::map<TString, TString> GetKeys();
+
+    virtual void InitStreamLocale(wios *stream) = 0;
+    virtual std::list<TString> LoadFromFile(TString FileName);
+    virtual void SaveToFile(TString FileName,
+             std::list<TString> Contents, bool ownerOnly);
+
+    virtual TString GetTempDirectory() = 0;
+
+    virtual void addPlatformDependencies(JavaLibrary *pJavaLibrary) = 0;
+
+public:
+    // String helpers
+    // Caller must free result using delete[].
+    static void CopyString(char *Destination,
+            size_t NumberOfElements, const char *Source);
+
+    // Caller must free result using delete[].
+    static void CopyString(wchar_t *Destination,
+            size_t NumberOfElements, const wchar_t *Source);
+
+    static WideString MultibyteStringToWideString(const char* value);
+    static MultibyteString WideStringToMultibyteString(const wchar_t* value);
+};
+
+class Exception: public std::exception {
+private:
+    TString FMessage;
+
+protected:
+    void SetMessage(const TString Message) {
+        FMessage = Message;
+    }
+
+public:
+    explicit Exception() : exception() {}
+    explicit Exception(const TString Message) : exception() {
+        SetMessage(Message);
+    }
+    virtual ~Exception() throw() {}
+
+    TString GetMessage() { return FMessage; }
+};
+
+#endif // PLATFORM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/PlatformString.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "PlatformString.h"
+
+#include "Helpers.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <sstream>
+#include <string.h>
+
+#include "jni.h"
+
+void PlatformString::initialize() {
+    FWideTStringToFree = NULL;
+    FLength = 0;
+    FData = NULL;
+}
+
+PlatformString::PlatformString(void) {
+    initialize();
+}
+
+PlatformString::~PlatformString(void) {
+    if (FData != NULL) {
+        delete[] FData;
+    }
+
+    if (FWideTStringToFree != NULL) {
+        delete[] FWideTStringToFree;
+    }
+}
+
+PlatformString::PlatformString(const PlatformString &value) {
+    initialize();
+    FLength = value.FLength;
+    FData = new char[FLength + 1];
+    Platform::CopyString(FData, FLength + 1, value.FData);
+}
+
+PlatformString::PlatformString(const char* value) {
+    initialize();
+    FLength = strlen(value);
+    FData = new char[FLength + 1];
+    Platform::CopyString(FData, FLength + 1, value);
+}
+
+PlatformString::PlatformString(size_t Value) {
+    initialize();
+
+    std::stringstream ss;
+    std::string s;
+    ss << Value;
+    s = ss.str();
+
+    FLength = strlen(s.c_str());
+    FData = new char[FLength + 1];
+    Platform::CopyString(FData, FLength + 1, s.c_str());
+}
+
+PlatformString::PlatformString(const wchar_t* value) {
+    initialize();
+    MultibyteString temp = Platform::WideStringToMultibyteString(value);
+    FLength = temp.length;
+    FData = temp.data;
+}
+
+PlatformString::PlatformString(const std::string &value) {
+    initialize();
+    const char* lvalue = value.data();
+    FLength = value.size();
+    FData = new char[FLength + 1];
+    Platform::CopyString(FData, FLength + 1, lvalue);
+}
+
+PlatformString::PlatformString(const std::wstring &value) {
+    initialize();
+    const wchar_t* lvalue = value.data();
+    MultibyteString temp = Platform::WideStringToMultibyteString(lvalue);
+    FLength = temp.length;
+    FData = temp.data;
+}
+
+TString PlatformString::Format(const TString value, ...) {
+    TString result = value;
+
+    va_list arglist;
+    va_start(arglist, value);
+
+    while (1) {
+        size_t pos = result.find(_T("%s"), 0);
+
+        if (pos == TString::npos) {
+            break;
+        }
+        else {
+            TCHAR* arg = va_arg(arglist, TCHAR*);
+
+            if (arg == NULL) {
+                break;
+            }
+            else {
+                result.replace(pos, StringLength(_T("%s")), arg);
+            }
+        }
+    }
+
+    va_end(arglist);
+
+    return result;
+}
+
+size_t PlatformString::length() {
+    return FLength;
+}
+
+char* PlatformString::c_str() {
+    return FData;
+}
+
+char* PlatformString::toMultibyte() {
+    return FData;
+}
+
+wchar_t* PlatformString::toWideString() {
+    WideString result = Platform::MultibyteStringToWideString(FData);
+
+    if (result.data != NULL) {
+        if (FWideTStringToFree != NULL) {
+            delete [] FWideTStringToFree;
+        }
+
+        FWideTStringToFree = result.data;
+    }
+
+    return result.data;
+}
+
+std::wstring PlatformString::toUnicodeString() {
+    std::wstring result;
+    wchar_t* data = toWideString();
+
+    if (FLength != 0 && data != NULL) {
+        // NOTE: Cleanup of result is handled by PlatformString destructor.
+        result = data;
+    }
+
+    return result;
+}
+
+std::string PlatformString::toStdString() {
+    std::string result;
+    char* data = toMultibyte();
+
+    if (FLength > 0 && data != NULL) {
+        result = data;
+    }
+
+    return result;
+}
+
+TCHAR* PlatformString::toPlatformString() {
+#ifdef _UNICODE
+    return toWideString();
+#else
+    return c_str();
+#endif //_UNICODE
+}
+
+TString PlatformString::toString() {
+#ifdef _UNICODE
+    return toUnicodeString();
+#else
+    return toStdString();
+#endif //_UNICODE
+}
+
+PlatformString::operator char* () {
+    return c_str();
+}
+
+PlatformString::operator wchar_t* () {
+    return toWideString();
+}
+
+PlatformString::operator std::wstring () {
+    return toUnicodeString();
+}
+
+char* PlatformString::duplicate(const char* Value) {
+    size_t length = strlen(Value);
+    char* result = new char[length + 1];
+    Platform::CopyString(result, length + 1, Value);
+    return result;
+}
+
+wchar_t* PlatformString::duplicate(const wchar_t* Value) {
+    size_t length = wcslen(Value);
+    wchar_t* result = new wchar_t[length + 1];
+    Platform::CopyString(result, length + 1, Value);
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/PlatformString.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef PLATFORMSTRING_H
+#define PLATFORMSTRING_H
+
+
+#include <string>
+#include <list>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "jni.h"
+#include "Platform.h"
+
+
+template <typename T>
+class DynamicBuffer {
+private:
+    T* FData;
+    size_t FSize;
+
+public:
+    DynamicBuffer(size_t Size) {
+        FSize = 0;
+        FData = NULL;
+        Resize(Size);
+    }
+
+    ~DynamicBuffer() {
+        delete[] FData;
+    }
+
+    T* GetData() { return FData; }
+    size_t GetSize() { return FSize; }
+
+    bool Resize(size_t Size) {
+        FSize = Size;
+
+        if (FData != NULL) {
+            delete[] FData;
+            FData = NULL;
+        }
+
+        if (FSize != 0) {
+            FData = new T[FSize];
+            if (FData != NULL) {
+                Zero();
+            } else {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    void Zero() {
+        memset(FData, 0, FSize * sizeof(T));
+    }
+
+    T& operator[](size_t index) {
+        return FData[index];
+    }
+};
+
+class PlatformString {
+private:
+    char* FData; // Stored as UTF-8
+    size_t FLength;
+    wchar_t* FWideTStringToFree;
+
+    void initialize();
+
+// Prohibit Heap-Based PlatformStrings
+private:
+    static void *operator new(size_t size);
+    static void operator delete(void *ptr);
+
+public:
+    PlatformString(void);
+    PlatformString(const PlatformString &value);
+    PlatformString(const char* value);
+    PlatformString(const wchar_t* value);
+    PlatformString(const std::string &value);
+    PlatformString(const std::wstring &value);
+    PlatformString(size_t Value);
+
+    static TString Format(const TString value, ...);
+
+    ~PlatformString(void);
+
+    size_t length();
+
+    char* c_str();
+    char* toMultibyte();
+    wchar_t* toWideString();
+    std::wstring toUnicodeString();
+    std::string toStdString();
+    TCHAR* toPlatformString();
+    TString toString();
+
+    operator char* ();
+    operator wchar_t* ();
+    operator std::wstring ();
+
+    // Caller must free result using delete[].
+    static char* duplicate(const char* Value);
+
+    // Caller must free result using delete[].
+    static wchar_t* duplicate(const wchar_t* Value);
+};
+
+
+#endif // PLATFORMSTRING_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/Properties.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef PROPERTIES_H
+#define PROPERTIES_H
+
+#include "PlatformDefs.h"
+#include "OrderedMap.h"
+
+//#include <stdio.h>
+//#include <stdlib.h>
+//#include <memory.h>
+//#include <string>
+//#include <map>
+//#include <list>
+//#include <vector>
+//#include <fstream>
+
+//using namespace std;
+
+template <typename ObjectType, typename ValueType,
+        ValueType (ObjectType::*getter)(void),
+        void (ObjectType::*setter)(ValueType)>
+class Property {
+private:
+    ObjectType* FObject;
+
+public:
+    Property() {
+        FObject = NULL;
+    }
+
+    void SetInstance(ObjectType* Value) {
+        FObject = Value;
+    }
+
+    // To set the value using the set method.
+    ValueType operator =(const ValueType& Value) {
+        assert(FObject != NULL);
+        (FObject->*setter)(Value);
+        return Value;
+    }
+
+    // The Property class is treated as the internal type.
+    operator ValueType() {
+        assert(FObject != NULL);
+        return (FObject->*getter)();
+    }
+};
+
+template <typename ObjectType, typename ValueType,
+        ValueType (ObjectType::*getter)(void)>
+class ReadProperty {
+private:
+    ObjectType* FObject;
+
+public:
+    ReadProperty() {
+        FObject = NULL;
+    }
+
+    void SetInstance(ObjectType* Value) {
+        FObject = Value;
+    }
+
+    // The Property class is treated as the internal type.
+    operator ValueType() {
+        assert(FObject != NULL);
+        return (FObject->*getter)();
+    }
+};
+
+template <typename ObjectType, typename ValueType,
+        void (ObjectType::*setter)(ValueType)>
+class WriteProperty {
+private:
+    ObjectType* FObject;
+
+public:
+    WriteProperty() {
+        FObject = NULL;
+    }
+
+    void SetInstance(ObjectType* Value) {
+        FObject = Value;
+    }
+
+    // To set the value using the set method.
+    ValueType operator =(const ValueType& Value) {
+        assert(FObject != NULL);
+        (FObject->*setter)(Value);
+        return Value;
+    }
+};
+
+template <typename ValueType,
+        ValueType (*getter)(void), void (*setter)(ValueType)>
+class StaticProperty {
+public:
+    StaticProperty() {
+    }
+
+    // To set the value using the set method.
+    ValueType operator =(const ValueType& Value) {
+        (*getter)(Value);
+        return Value;
+    }
+
+    // The Property class is treated as the internal type which is the getter.
+    operator ValueType() {
+        return (*setter)();
+    }
+};
+
+template <typename ValueType, ValueType (*getter)(void)>
+class StaticReadProperty {
+public:
+    StaticReadProperty() {
+    }
+
+    // The Property class is treated as the internal type which is the getter.
+    operator ValueType() {
+        return (*getter)();
+    }
+};
+
+template <typename ValueType, void (*setter)(ValueType)>
+class StaticWriteProperty {
+public:
+    StaticWriteProperty() {
+    }
+
+    // To set the value using the set method.
+    ValueType operator =(const ValueType& Value) {
+        (*setter)(Value);
+        return Value;
+    }
+};
+
+class IPropertyContainer {
+public:
+    IPropertyContainer(void) {}
+    virtual ~IPropertyContainer(void) {}
+
+    virtual bool GetValue(const TString Key, TString& Value) = 0;
+    virtual size_t GetCount() = 0;
+};
+
+class ISectionalPropertyContainer {
+public:
+    ISectionalPropertyContainer(void) {}
+    virtual ~ISectionalPropertyContainer(void) {}
+
+    virtual bool GetValue(const TString SectionName,
+            const TString Key, TString& Value) = 0;
+    virtual bool ContainsSection(const TString SectionName) = 0;
+    virtual bool GetSection(const TString SectionName,
+            OrderedMap<TString, TString> &Data) = 0;
+};
+
+#endif // PROPERTIES_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/PropertyFile.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "PropertyFile.h"
+
+#include "Helpers.h"
+#include "FilePath.h"
+
+#include <string>
+
+
+PropertyFile::PropertyFile(void) : IPropertyContainer() {
+    FReadOnly = false;
+    FModified = false;
+}
+
+PropertyFile::PropertyFile(const TString FileName) : IPropertyContainer() {
+    FReadOnly = true;
+    FModified = false;
+    LoadFromFile(FileName);
+}
+
+PropertyFile::PropertyFile(OrderedMap<TString, TString> Value) {
+    FData.Append(Value);
+}
+
+PropertyFile::PropertyFile(PropertyFile &Value) {
+    FData = Value.FData;
+    FReadOnly = Value.FReadOnly;
+    FModified = Value.FModified;
+}
+
+PropertyFile::~PropertyFile(void) {
+    FData.Clear();
+}
+
+void PropertyFile::SetModified(bool Value) {
+    FModified = Value;
+}
+
+bool PropertyFile::IsModified() {
+    return FModified;
+}
+
+bool PropertyFile::GetReadOnly() {
+    return FReadOnly;
+}
+
+void PropertyFile::SetReadOnly(bool Value) {
+    FReadOnly = Value;
+}
+
+bool PropertyFile::LoadFromFile(const TString FileName) {
+    bool result = false;
+    Platform& platform = Platform::GetInstance();
+
+    std::list<TString> contents = platform.LoadFromFile(FileName);
+
+    if (contents.empty() == false) {
+        for (std::list<TString>::const_iterator iterator = contents.begin();
+                iterator != contents.end(); iterator++) {
+            TString line = *iterator;
+            TString name;
+            TString value;
+
+            if (Helpers::SplitOptionIntoNameValue(line, name, value) == true) {
+                FData.Append(name, value);
+            }
+        }
+
+        SetModified(false);
+        result = true;
+    }
+
+    return result;
+}
+
+bool PropertyFile::SaveToFile(const TString FileName, bool ownerOnly) {
+    bool result = false;
+
+    if (GetReadOnly() == false && IsModified()) {
+        std::list<TString> contents;
+        std::vector<TString> keys = FData.GetKeys();
+
+        for (size_t index = 0; index < keys.size(); index++) {
+            TString name = keys[index];
+
+            try {
+                TString value;// = FData[index];
+
+                if (FData.GetValue(name, value) == true) {
+                    TString line = name + _T('=') + value;
+                    contents.push_back(line);
+                }
+            }
+            catch (std::out_of_range &) {
+            }
+        }
+
+        Platform& platform = Platform::GetInstance();
+        platform.SaveToFile(FileName, contents, ownerOnly);
+
+        SetModified(false);
+        result = true;
+    }
+
+    return result;
+}
+
+bool PropertyFile::GetValue(const TString Key, TString& Value) {
+    return FData.GetValue(Key, Value);
+}
+
+bool PropertyFile::SetValue(const TString Key, TString Value) {
+    bool result = false;
+
+    if (GetReadOnly() == false) {
+        FData.SetValue(Key, Value);
+        SetModified(true);
+        result = true;
+    }
+
+    return result;
+}
+
+bool PropertyFile::RemoveKey(const TString Key) {
+    bool result = false;
+
+    if (GetReadOnly() == false) {
+        result = FData.RemoveByKey(Key);
+
+        if (result == true) {
+            SetModified(true);
+        }
+    }
+
+    return result;
+}
+
+size_t PropertyFile::GetCount() {
+    return FData.Count();
+}
+
+OrderedMap<TString, TString> PropertyFile::GetData() {
+    return FData;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/PropertyFile.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef PROPERTYFILE_H
+#define PROPERTYFILE_H
+
+#include "Platform.h"
+#include "Helpers.h"
+
+
+class PropertyFile : public IPropertyContainer {
+private:
+    bool FReadOnly;
+    bool FModified;
+    OrderedMap<TString, TString> FData;
+
+    void SetModified(bool Value);
+
+public:
+    PropertyFile(void);
+    PropertyFile(const TString FileName);
+    PropertyFile(OrderedMap<TString, TString> Value);
+    PropertyFile(PropertyFile &Value);
+    virtual ~PropertyFile(void);
+
+    bool IsModified();
+    bool GetReadOnly();
+    void SetReadOnly(bool Value);
+
+    bool LoadFromFile(const TString FileName);
+    bool SaveToFile(const TString FileName, bool ownerOnly = true);
+
+    bool SetValue(const TString Key, TString Value);
+    bool RemoveKey(const TString Key);
+
+    OrderedMap<TString, TString> GetData();
+
+    // IPropertyContainer
+    virtual bool GetValue(const TString Key, TString& Value);
+    virtual size_t GetCount();
+};
+
+#endif // PROPERTYFILE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/share/native/libapplauncher/main.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "Platform.h"
+#include "PlatformString.h"
+#include "FilePath.h"
+#include "PropertyFile.h"
+#include "JavaVirtualMachine.h"
+#include "Package.h"
+#include "Macros.h"
+#include "Messages.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+
+/*
+This is the app launcher program for application packaging on Windows, Mac,
+    and Linux.
+
+Basic approach:
+  - Launcher (jpackageapplauncher) is executable that loads
+    applauncher.dll/libapplauncher.dylib/libapplauncher.so
+    and calls start_launcher below.
+  - Reads app/package.cfg or Info.plist or app/<appname>.cfg for application
+    launch configuration (package.cfg is property file).
+  - Load Java with requested Java settings (bundled client Java if availble,
+    server or installed Java otherwise).
+  - Wait for Java to exit and then exit from Main
+  - To debug application by passing command line argument.
+  - Application folder is added to the library path (so LoadLibrary()) works.
+
+Limitations and future work:
+  - Running Java code in primordial thread may cause problems
+    (example: can not use custom stack size).
+    Solution used by java launcher is to create a new thread to invoke Java.
+    See CR 6316197 for more information.
+*/
+
+extern "C" {
+
+    JNIEXPORT bool start_launcher(int argc, TCHAR* argv[]) {
+        bool result = false;
+        bool parentProcess = true;
+
+        // Platform must be initialize first.
+        Platform& platform = Platform::GetInstance();
+
+        try {
+            for (int index = 0; index < argc; index++) {
+                TString argument = argv[index];
+
+                if (argument == _T("-Xappcds:generatecache")) {
+                    platform.SetAppCDSState(cdsGenCache);
+                }
+                else if (argument == _T("-Xappcds:off")) {
+                    platform.SetAppCDSState(cdsDisabled);
+                }
+                else if (argument == _T("-Xapp:child")) {
+                    parentProcess = false;
+                }
+            }
+
+            // Package must be initialized after Platform is fully initialized.
+            Package& package = Package::GetInstance();
+            Macros::Initialize();
+            package.SetCommandLineArguments(argc, argv);
+
+            switch (platform.GetAppCDSState()) {
+                case cdsDisabled:
+                case cdsUninitialized:
+                case cdsEnabled: {
+                    break;
+                }
+
+                case cdsGenCache: {
+                    TString cacheDirectory = package.GetAppCDSCacheDirectory();
+
+                    if (FilePath::DirectoryExists(cacheDirectory) == false) {
+                        FilePath::CreateDirectory(cacheDirectory, true);
+                    } else {
+                        TString cacheFileName =
+                                package.GetAppCDSCacheFileName();
+                        if (FilePath::FileExists(cacheFileName) == true) {
+                            FilePath::DeleteFile(cacheFileName);
+                        }
+                    }
+
+                    break;
+                }
+
+                case cdsAuto: {
+                    TString cacheFileName = package.GetAppCDSCacheFileName();
+
+                    if (parentProcess == true &&
+                            FilePath::FileExists(cacheFileName) == false) {
+                        AutoFreePtr<Process> process = platform.CreateProcess();
+                        std::vector<TString> args;
+                        args.push_back(_T("-Xappcds:generatecache"));
+                        args.push_back(_T("-Xapp:child"));
+                        process->Execute(
+                                platform.GetModuleFileName(), args, true);
+
+                        if (FilePath::FileExists(cacheFileName) == false) {
+                            // Cache does not exist after trying to generate it,
+                            // so run without cache.
+                            platform.SetAppCDSState(cdsDisabled);
+                            package.Clear();
+                            package.Initialize();
+                        }
+                    }
+
+                    break;
+                }
+            }
+
+            // Validation
+            switch (platform.GetAppCDSState()) {
+                case cdsDisabled:
+                case cdsGenCache: {
+                    // Do nothing.
+                    break;
+                }
+
+                case cdsEnabled:
+                case cdsAuto: {
+                    TString cacheFileName =
+                            package.GetAppCDSCacheFileName();
+
+                    if (FilePath::FileExists(cacheFileName) == false) {
+                        Messages& messages = Messages::GetInstance();
+                        TString message = PlatformString::Format(
+                                messages.GetMessage(
+                                APPCDS_CACHE_FILE_NOT_FOUND),
+                                cacheFileName.data());
+                        throw Exception(message);
+                    }
+                    break;
+                }
+
+                case cdsUninitialized: {
+                    platform.ShowMessage(_T("Internal Error"));
+                    break;
+                }
+            }
+
+            // Run App
+            result = RunVM();
+        } catch (Exception &e) {
+            platform.ShowMessage(e.GetMessage());
+        }
+
+        return result;
+    }
+
+    JNIEXPORT void stop_launcher() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/unix/native/libapplauncher/FileAttribute.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef FILEATTRIBUTE_H
+#define FILEATTRIBUTE_H
+
+enum FileAttribute {
+    faBlockSpecial,
+    faCharacterSpecial,
+    faFIFOSpecial,
+    faNormal,
+    faDirectory,
+    faSymbolicLink,
+    faSocket,
+
+    // Owner
+    faReadOnly,
+    faWriteOnly,
+    faReadWrite,
+    faExecute,
+
+    // Group
+    faGroupReadOnly,
+    faGroupWriteOnly,
+    faGroupReadWrite,
+    faGroupExecute,
+
+    // Others
+    faOthersReadOnly,
+    faOthersWriteOnly,
+    faOthersReadWrite,
+    faOthersExecute,
+
+    faHidden
+};
+
+#endif // FILEATTRIBUTE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/unix/native/libapplauncher/FileAttributes.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "FileAttributes.h"
+
+#include <algorithm>
+#include <list>
+#include <sys/stat.h>
+
+FileAttributes::FileAttributes(const TString FileName, bool FollowLink) {
+    FFileName = FileName;
+    FFollowLink = FollowLink;
+    ReadAttributes();
+}
+
+bool FileAttributes::WriteAttributes() {
+    bool result = false;
+
+    mode_t attributes = 0;
+
+    for (std::vector<FileAttribute>::const_iterator iterator =
+            FAttributes.begin();
+            iterator != FAttributes.end(); iterator++) {
+        switch (*iterator) {
+            case faBlockSpecial:
+            {
+                attributes |= S_IFBLK;
+                break;
+            }
+            case faCharacterSpecial:
+            {
+                attributes |= S_IFCHR;
+                break;
+            }
+            case faFIFOSpecial:
+            {
+                attributes |= S_IFIFO;
+                break;
+            }
+            case faNormal:
+            {
+                attributes |= S_IFREG;
+                break;
+            }
+            case faDirectory:
+            {
+                attributes |= S_IFDIR;
+                break;
+            }
+            case faSymbolicLink:
+            {
+                attributes |= S_IFLNK;
+                break;
+            }
+            case faSocket:
+            {
+                attributes |= S_IFSOCK;
+                break;
+            }
+
+                // Owner
+            case faReadOnly:
+            {
+                attributes |= S_IRUSR;
+                break;
+            }
+            case faWriteOnly:
+            {
+                attributes |= S_IWUSR;
+                break;
+            }
+            case faReadWrite:
+            {
+                attributes |= S_IRUSR;
+                attributes |= S_IWUSR;
+                break;
+            }
+            case faExecute:
+            {
+                attributes |= S_IXUSR;
+                break;
+            }
+
+                // Group
+            case faGroupReadOnly:
+            {
+                attributes |= S_IRGRP;
+                break;
+            }
+            case faGroupWriteOnly:
+            {
+                attributes |= S_IWGRP;
+                break;
+            }
+            case faGroupReadWrite:
+            {
+                attributes |= S_IRGRP;
+                attributes |= S_IWGRP;
+                break;
+            }
+            case faGroupExecute:
+            {
+                attributes |= S_IXGRP;
+                break;
+            }
+
+                // Others
+            case faOthersReadOnly:
+            {
+                attributes |= S_IROTH;
+                break;
+            }
+            case faOthersWriteOnly:
+            {
+                attributes |= S_IWOTH;
+                break;
+            }
+            case faOthersReadWrite:
+            {
+                attributes |= S_IROTH;
+                attributes |= S_IWOTH;
+                break;
+            }
+            case faOthersExecute:
+            {
+                attributes |= S_IXOTH;
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    if (chmod(FFileName.data(), attributes) == 0) {
+        result = true;
+    }
+
+    return result;
+}
+
+#define S_ISRUSR(m)    (((m) & S_IRWXU) == S_IRUSR)
+#define S_ISWUSR(m)    (((m) & S_IRWXU) == S_IWUSR)
+#define S_ISXUSR(m)    (((m) & S_IRWXU) == S_IXUSR)
+
+#define S_ISRGRP(m)    (((m) & S_IRWXG) == S_IRGRP)
+#define S_ISWGRP(m)    (((m) & S_IRWXG) == S_IWGRP)
+#define S_ISXGRP(m)    (((m) & S_IRWXG) == S_IXGRP)
+
+#define S_ISROTH(m)    (((m) & S_IRWXO) == S_IROTH)
+#define S_ISWOTH(m)    (((m) & S_IRWXO) == S_IWOTH)
+#define S_ISXOTH(m)    (((m) & S_IRWXO) == S_IXOTH)
+
+bool FileAttributes::ReadAttributes() {
+    bool result = false;
+
+    struct stat status;
+
+    if (stat(StringToFileSystemString(FFileName), &status) == 0) {
+        result = true;
+
+        if (S_ISBLK(status.st_mode) != 0) {
+            FAttributes.push_back(faBlockSpecial);
+        }
+        if (S_ISCHR(status.st_mode) != 0) {
+            FAttributes.push_back(faCharacterSpecial);
+        }
+        if (S_ISFIFO(status.st_mode) != 0) {
+            FAttributes.push_back(faFIFOSpecial);
+        }
+        if (S_ISREG(status.st_mode) != 0) {
+            FAttributes.push_back(faNormal);
+        }
+        if (S_ISDIR(status.st_mode) != 0) {
+            FAttributes.push_back(faDirectory);
+        }
+        if (S_ISLNK(status.st_mode) != 0) {
+            FAttributes.push_back(faSymbolicLink);
+        }
+        if (S_ISSOCK(status.st_mode) != 0) {
+            FAttributes.push_back(faSocket);
+        }
+
+        // Owner
+        if (S_ISRUSR(status.st_mode) != 0) {
+            if (S_ISWUSR(status.st_mode) != 0) {
+                FAttributes.push_back(faReadWrite);
+            } else {
+                FAttributes.push_back(faReadOnly);
+            }
+        } else if (S_ISWUSR(status.st_mode) != 0) {
+            FAttributes.push_back(faWriteOnly);
+        }
+
+        if (S_ISXUSR(status.st_mode) != 0) {
+            FAttributes.push_back(faExecute);
+        }
+
+        // Group
+        if (S_ISRGRP(status.st_mode) != 0) {
+            if (S_ISWGRP(status.st_mode) != 0) {
+                FAttributes.push_back(faGroupReadWrite);
+            } else {
+                FAttributes.push_back(faGroupReadOnly);
+            }
+        } else if (S_ISWGRP(status.st_mode) != 0) {
+            FAttributes.push_back(faGroupWriteOnly);
+        }
+
+        if (S_ISXGRP(status.st_mode) != 0) {
+            FAttributes.push_back(faGroupExecute);
+        }
+
+
+        // Others
+        if (S_ISROTH(status.st_mode) != 0) {
+            if (S_ISWOTH(status.st_mode) != 0) {
+                FAttributes.push_back(faOthersReadWrite);
+            } else {
+                FAttributes.push_back(faOthersReadOnly);
+            }
+        } else if (S_ISWOTH(status.st_mode) != 0) {
+            FAttributes.push_back(faOthersWriteOnly);
+        }
+
+        if (S_ISXOTH(status.st_mode) != 0) {
+            FAttributes.push_back(faOthersExecute);
+        }
+
+        if (FFileName.size() > 0 && FFileName[0] == '.') {
+            FAttributes.push_back(faHidden);
+        }
+    }
+
+    return result;
+}
+
+bool FileAttributes::Valid(const FileAttribute Value) {
+    bool result = false;
+
+    switch (Value) {
+        case faReadWrite:
+        case faWriteOnly:
+        case faExecute:
+
+        case faGroupReadWrite:
+        case faGroupWriteOnly:
+        case faGroupReadOnly:
+        case faGroupExecute:
+
+        case faOthersReadWrite:
+        case faOthersWriteOnly:
+        case faOthersReadOnly:
+        case faOthersExecute:
+
+        case faReadOnly:
+            result = true;
+            break;
+
+        default:
+            break;
+    }
+
+    return result;
+}
+
+void FileAttributes::Append(FileAttribute Value) {
+    if (Valid(Value) == true) {
+        if ((Value == faReadOnly && Contains(faWriteOnly) == true) ||
+                (Value == faWriteOnly && Contains(faReadOnly) == true)) {
+            Value = faReadWrite;
+        }
+
+        FAttributes.push_back(Value);
+        WriteAttributes();
+    }
+}
+
+bool FileAttributes::Contains(FileAttribute Value) {
+    bool result = false;
+
+    std::vector<FileAttribute>::const_iterator iterator =
+            std::find(FAttributes.begin(), FAttributes.end(), Value);
+
+    if (iterator != FAttributes.end()) {
+        result = true;
+    }
+
+    return result;
+}
+
+void FileAttributes::Remove(FileAttribute Value) {
+    if (Valid(Value) == true) {
+        if (Value == faReadOnly && Contains(faReadWrite) == true) {
+            Append(faWriteOnly);
+            Remove(faReadWrite);
+        } else if (Value == faWriteOnly && Contains(faReadWrite) == true) {
+            Append(faReadOnly);
+            Remove(faReadWrite);
+        }
+
+        std::vector<FileAttribute>::iterator iterator =
+                std::find(FAttributes.begin(), FAttributes.end(), Value);
+
+        if (iterator != FAttributes.end()) {
+            FAttributes.erase(iterator);
+            WriteAttributes();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/unix/native/libapplauncher/FilePath.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "PlatformDefs.h"
+#include "FilePath.h"
+
+#include <algorithm>
+#include <list>
+#include <sys/stat.h>
+
+bool FilePath::FileExists(const TString FileName) {
+    bool result = false;
+    struct stat buf;
+
+    if ((stat(StringToFileSystemString(FileName), &buf) == 0) &&
+            (S_ISREG(buf.st_mode) != 0)) {
+        result = true;
+    }
+
+    return result;
+}
+
+bool FilePath::DirectoryExists(const TString DirectoryName) {
+    bool result = false;
+
+    struct stat buf;
+
+    if ((stat(StringToFileSystemString(DirectoryName), &buf) == 0) &&
+            (S_ISDIR(buf.st_mode) != 0)) {
+        result = true;
+    }
+
+    return result;
+}
+
+bool FilePath::DeleteFile(const TString FileName) {
+    bool result = false;
+
+    if (FileExists(FileName) == true) {
+        if (unlink(StringToFileSystemString(FileName)) == 0) {
+            result = true;
+        }
+    }
+
+    return result;
+}
+
+bool FilePath::DeleteDirectory(const TString DirectoryName) {
+    bool result = false;
+
+    if (DirectoryExists(DirectoryName) == true) {
+        if (unlink(StringToFileSystemString(DirectoryName)) == 0) {
+            result = true;
+        }
+    }
+
+    return result;
+}
+
+TString FilePath::IncludeTrailingSeparator(const TString value) {
+    TString result = value;
+
+    if (value.size() > 0) {
+        TString::iterator i = result.end();
+        i--;
+
+        if (*i != TRAILING_PATHSEPARATOR) {
+            result += TRAILING_PATHSEPARATOR;
+        }
+    }
+
+    return result;
+}
+
+TString FilePath::IncludeTrailingSeparator(const char* value) {
+    TString lvalue = PlatformString(value).toString();
+    return IncludeTrailingSeparator(lvalue);
+}
+
+TString FilePath::IncludeTrailingSeparator(const wchar_t* value) {
+    TString lvalue = PlatformString(value).toString();
+    return IncludeTrailingSeparator(lvalue);
+}
+
+TString FilePath::ExtractFilePath(TString Path) {
+    return dirname(StringToFileSystemString(Path));
+}
+
+TString FilePath::ExtractFileExt(TString Path) {
+    TString result;
+    size_t dot = Path.find_last_of('.');
+
+    if (dot != TString::npos) {
+        result = Path.substr(dot, Path.size() - dot);
+    }
+
+    return result;
+}
+
+TString FilePath::ExtractFileName(TString Path) {
+    return basename(StringToFileSystemString(Path));
+}
+
+TString FilePath::ChangeFileExt(TString Path, TString Extension) {
+    TString result;
+    size_t dot = Path.find_last_of('.');
+
+    if (dot != TString::npos) {
+        result = Path.substr(0, dot) + Extension;
+    }
+
+    if (result.empty() == true) {
+        result = Path;
+    }
+
+    return result;
+}
+
+TString FilePath::FixPathForPlatform(TString Path) {
+    TString result = Path;
+    std::replace(result.begin(), result.end(),
+            BAD_TRAILING_PATHSEPARATOR, TRAILING_PATHSEPARATOR);
+    return result;
+}
+
+TString FilePath::FixPathSeparatorForPlatform(TString Path) {
+    TString result = Path;
+    std::replace(result.begin(), result.end(),
+            BAD_PATH_SEPARATOR, PATH_SEPARATOR);
+    return result;
+}
+
+TString FilePath::PathSeparator() {
+    TString result;
+    result = PATH_SEPARATOR;
+    return result;
+}
+
+bool FilePath::CreateDirectory(TString Path, bool ownerOnly) {
+    bool result = false;
+
+    std::list<TString> paths;
+    TString lpath = Path;
+
+    while (lpath.empty() == false && DirectoryExists(lpath) == false) {
+        paths.push_front(lpath);
+        lpath = ExtractFilePath(lpath);
+    }
+
+    for (std::list<TString>::iterator iterator = paths.begin();
+            iterator != paths.end(); iterator++) {
+        lpath = *iterator;
+
+        mode_t mode = S_IRWXU;
+        if (!ownerOnly) {
+            mode |= S_IRWXG | S_IROTH | S_IXOTH;
+        }
+        if (mkdir(StringToFileSystemString(lpath), mode) == 0) {
+            result = true;
+        } else {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+void FilePath::ChangePermissions(TString FileName, bool ownerOnly) {
+    mode_t mode = S_IRWXU;
+    if (!ownerOnly) {
+        mode |= S_IRWXG | S_IROTH | S_IXOTH;
+    }
+    chmod(FileName.data(), mode);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/unix/native/libapplauncher/PosixPlatform.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "PosixPlatform.h"
+
+#include "PlatformString.h"
+#include "FilePath.h"
+#include "Helpers.h"
+
+#include <assert.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+#include <iostream>
+#include <algorithm>
+#include <dlfcn.h>
+#include <signal.h>
+
+using namespace std;
+
+PosixPlatform::PosixPlatform(void) {
+}
+
+PosixPlatform::~PosixPlatform(void) {
+}
+
+TString PosixPlatform::GetTempDirectory() {
+    struct passwd* pw = getpwuid(getuid());
+    TString homedir(pw->pw_dir);
+    homedir += getTmpDirString();
+    if (!FilePath::DirectoryExists(homedir)) {
+        if (!FilePath::CreateDirectory(homedir, false)) {
+            homedir.clear();
+        }
+    }
+
+    return homedir;
+}
+
+TString PosixPlatform::fixName(const TString& name) {
+    TString fixedName(name);
+    const TString chars("?:*<>/\\");
+    for (TString::const_iterator it = chars.begin(); it != chars.end(); it++) {
+        fixedName.erase(std::remove(fixedName.begin(),
+                fixedName.end(), *it), fixedName.end());
+    }
+    return fixedName;
+}
+
+MessageResponse PosixPlatform::ShowResponseMessage(TString title,
+        TString description) {
+    MessageResponse result = mrCancel;
+
+    printf("%s %s (Y/N)\n", PlatformString(title).toPlatformString(),
+            PlatformString(description).toPlatformString());
+    fflush(stdout);
+
+    std::string input;
+    std::cin >> input;
+
+    if (input == "Y") {
+        result = mrOK;
+    }
+
+    return result;
+}
+
+Module PosixPlatform::LoadLibrary(TString FileName) {
+    return dlopen(StringToFileSystemString(FileName), RTLD_LAZY);
+}
+
+void PosixPlatform::FreeLibrary(Module AModule) {
+    dlclose(AModule);
+}
+
+Procedure PosixPlatform::GetProcAddress(Module AModule,
+        std::string MethodName) {
+    return dlsym(AModule, PlatformString(MethodName));
+}
+
+Process* PosixPlatform::CreateProcess() {
+    return new PosixProcess();
+}
+
+void PosixPlatform::addPlatformDependencies(JavaLibrary *pJavaLibrary) {
+}
+
+void Platform::CopyString(char *Destination,
+        size_t NumberOfElements, const char *Source) {
+    strncpy(Destination, Source, NumberOfElements);
+
+    if (NumberOfElements > 0) {
+        Destination[NumberOfElements - 1] = '\0';
+    }
+}
+
+void Platform::CopyString(wchar_t *Destination,
+        size_t NumberOfElements, const wchar_t *Source) {
+    wcsncpy(Destination, Source, NumberOfElements);
+
+    if (NumberOfElements > 0) {
+        Destination[NumberOfElements - 1] = '\0';
+    }
+}
+
+// Owner must free the return value.
+
+MultibyteString Platform::WideStringToMultibyteString(
+        const wchar_t* value) {
+    MultibyteString result;
+    size_t count = 0;
+
+    if (value == NULL) {
+        return result;
+    }
+
+    count = wcstombs(NULL, value, 0);
+    if (count > 0) {
+        result.data = new char[count + 1];
+        result.data[count] = '\0';
+        result.length = count;
+        wcstombs(result.data, value, count);
+    }
+
+    return result;
+}
+
+// Owner must free the return value.
+
+WideString Platform::MultibyteStringToWideString(const char* value) {
+    WideString result;
+    size_t count = 0;
+
+    if (value == NULL) {
+        return result;
+    }
+
+    count = mbstowcs(NULL, value, 0);
+    if (count > 0) {
+        result.data = new wchar_t[count + 1];
+        result.data[count] = '\0';
+        result.length = count;
+        mbstowcs(result.data, value, count);
+    }
+
+    return result;
+}
+
+void PosixPlatform::InitStreamLocale(wios *stream) {
+    // Nothing to do for POSIX platforms.
+}
+
+PosixProcess::PosixProcess() : Process() {
+    FChildPID = 0;
+    FRunning = false;
+    FOutputHandle = 0;
+    FInputHandle = 0;
+}
+
+PosixProcess::~PosixProcess() {
+    Terminate();
+}
+
+bool PosixProcess::ReadOutput() {
+    bool result = false;
+
+    if (FOutputHandle != 0 && IsRunning() == true) {
+        char buffer[4096] = {0};
+
+        ssize_t count = read(FOutputHandle, buffer, sizeof (buffer));
+
+        if (count == -1) {
+            if (errno == EINTR) {
+                // continue;
+            } else {
+                perror("read");
+                exit(1);
+            }
+        } else if (count == 0) {
+            // break;
+        } else {
+            std::list<TString> output = Helpers::StringToArray(buffer);
+            FOutput.splice(FOutput.end(), output, output.begin(), output.end());
+            result = true;
+        }
+    }
+
+    return false;
+}
+
+bool PosixProcess::IsRunning() {
+    bool result = false;
+
+    if (kill(FChildPID, 0) == 0) {
+        result = true;
+    }
+
+    return result;
+}
+
+bool PosixProcess::Terminate() {
+    bool result = false;
+
+    if (IsRunning() == true && FRunning == true) {
+        FRunning = false;
+        Cleanup();
+        int status = kill(FChildPID, SIGTERM);
+
+        if (status == 0) {
+            result = true;
+        } else {
+#ifdef DEBUG
+            if (errno == EINVAL) {
+                printf("Kill error: The value of the sig argument is an invalid or unsupported signal number.");
+            } else if (errno == EPERM) {
+                printf("Kill error: The process does not have permission to send the signal to any receiving process.");
+            } else if (errno == ESRCH) {
+                printf("Kill error: No process or process group can be found corresponding to that specified by pid.");
+            }
+#endif // DEBUG
+            if (IsRunning() == true) {
+                status = kill(FChildPID, SIGKILL);
+
+                if (status == 0) {
+                    result = true;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+bool PosixProcess::Wait() {
+    bool result = false;
+
+    int status = 0;
+    pid_t wpid = 0;
+
+    wpid = wait(&status);
+    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+        if (errno != EINTR) {
+            status = -1;
+        }
+    }
+
+#ifdef DEBUG
+    if (WIFEXITED(status)) {
+        printf("child exited, status=%d\n", WEXITSTATUS(status));
+    } else if (WIFSIGNALED(status)) {
+        printf("child killed (signal %d)\n", WTERMSIG(status));
+    } else if (WIFSTOPPED(status)) {
+        printf("child stopped (signal %d)\n", WSTOPSIG(status));
+#ifdef WIFCONTINUED // Not all implementations support this
+    } else if (WIFCONTINUED(status)) {
+        printf("child continued\n");
+#endif // WIFCONTINUED
+    } else { // Non-standard case -- may never happen
+        printf("Unexpected status (0x%x)\n", status);
+    }
+#endif // DEBUG
+
+    if (wpid != -1) {
+        result = true;
+    }
+
+    return result;
+}
+
+TProcessID PosixProcess::GetProcessID() {
+    return FChildPID;
+}
+
+void PosixProcess::SetInput(TString Value) {
+    if (FInputHandle != 0) {
+        if (write(FInputHandle, Value.data(), Value.size()) < 0) {
+            throw Exception(_T("Internal Error - write failed"));
+        }
+    }
+}
+
+std::list<TString> PosixProcess::GetOutput() {
+    ReadOutput();
+    return Process::GetOutput();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/unix/native/libapplauncher/PosixPlatform.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef POSIXPLATFORM_H
+#define POSIXPLATFORM_H
+
+#include "Platform.h"
+#include <signal.h>
+
+class PosixPlatform : virtual public Platform {
+protected:
+
+    TString fixName(const TString& name);
+
+    virtual TString getTmpDirString() = 0;
+
+public:
+    PosixPlatform(void);
+    virtual ~PosixPlatform(void);
+
+public:
+    virtual MessageResponse ShowResponseMessage(TString title,
+            TString description);
+
+    virtual Module LoadLibrary(TString FileName);
+    virtual void FreeLibrary(Module AModule);
+    virtual Procedure GetProcAddress(Module AModule, std::string MethodName);
+
+    virtual Process* CreateProcess();
+    virtual TString GetTempDirectory();
+    void InitStreamLocale(wios *stream);
+    void addPlatformDependencies(JavaLibrary *pJavaLibrary);
+};
+
+class PosixProcess : public Process {
+private:
+    pid_t FChildPID;
+    sigset_t saveblock;
+    int FOutputHandle;
+    int FInputHandle;
+    struct sigaction savintr, savequit;
+    bool FRunning;
+
+    void Cleanup();
+    bool ReadOutput();
+
+public:
+    PosixProcess();
+    virtual ~PosixProcess();
+
+    virtual bool IsRunning();
+    virtual bool Terminate();
+    virtual bool Execute(const TString Application,
+            const std::vector<TString> Arguments, bool AWait = false);
+    virtual bool Wait();
+    virtual TProcessID GetProcessID();
+    virtual void SetInput(TString Value);
+    virtual std::list<TString> GetOutput();
+};
+
+#endif // POSIXPLATFORM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinAppBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+import java.util.*;
+
+import static jdk.incubator.jpackage.internal.WindowsBundlerParam.*;
+
+public class WinAppBundler extends AbstractImageBundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.WinResources");
+
+    static final BundlerParamInfo<File> ICON_ICO =
+            new StandardBundlerParam<>(
+            "icon.ico",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".ico")) {
+                    Log.error(MessageFormat.format(
+                            I18N.getString("message.icon-not-ico"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws ConfigException {
+        try {
+            Objects.requireNonNull(params);
+            return doValidate(params);
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    // to be used by chained bundlers, e.g. by EXE bundler to avoid
+    // skipping validation if p.type does not include "image"
+    private boolean doValidate(Map<String, ? super Object> p)
+            throws ConfigException {
+
+        imageBundleValidation(p);
+        return true;
+    }
+
+    public boolean bundle(Map<String, ? super Object> p, File outputDirectory)
+            throws PackagerException {
+        return doBundle(p, outputDirectory, false) != null;
+    }
+
+    File doBundle(Map<String, ? super Object> p, File outputDirectory,
+            boolean dependentTask) throws PackagerException {
+        if (StandardBundlerParam.isRuntimeInstaller(p)) {
+            return PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
+        } else {
+            return doAppBundle(p, outputDirectory, dependentTask);
+        }
+    }
+
+    File doAppBundle(Map<String, ? super Object> p, File outputDirectory,
+            boolean dependentTask) throws PackagerException {
+        try {
+            File rootDirectory = createRoot(p, outputDirectory, dependentTask,
+                    APP_NAME.fetchFrom(p));
+            AbstractAppImageBuilder appBuilder =
+                    new WindowsAppImageBuilder(p, outputDirectory.toPath());
+            if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {
+                JLinkBundlerHelper.execute(p, appBuilder);
+            } else {
+                StandardBundlerParam.copyPredefinedRuntimeImage(p, appBuilder);
+            }
+            if (!dependentTask) {
+                Log.verbose(MessageFormat.format(
+                        I18N.getString("message.result-dir"),
+                        outputDirectory.getAbsolutePath()));
+            }
+            return rootDirectory;
+        } catch (PackagerException pe) {
+            throw pe;
+        } catch (Exception e) {
+            Log.verbose(e);
+            throw new PackagerException(e);
+        }
+    }
+
+    @Override
+    public String getName() {
+        return I18N.getString("app.bundler.name");
+    }
+
+    @Override
+    public String getID() {
+        return "windows.app";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "IMAGE";
+    }
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) throws PackagerException {
+        return doBundle(params, outputParentDir, false);
+    }
+
+    @Override
+    public boolean supported(boolean platformInstaller) {
+        return true;
+    }
+
+    @Override
+    public boolean isDefault() {
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinExeBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2017, 2019, 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.incubator.jpackage.internal;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.MessageFormat;
+import java.util.*;
+
+public class WinExeBundler extends AbstractBundler {
+
+    static {
+        System.loadLibrary("jpackage");
+    }
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.WinResources");
+
+    public static final BundlerParamInfo<WinAppBundler> APP_BUNDLER
+            = new WindowsBundlerParam<>(
+                    "win.app.bundler",
+                    WinAppBundler.class,
+                    params -> new WinAppBundler(),
+                    null);
+
+    public static final BundlerParamInfo<File> EXE_IMAGE_DIR
+            = new WindowsBundlerParam<>(
+                    "win.exe.imageDir",
+                    File.class,
+                    params -> {
+                        File imagesRoot = IMAGES_ROOT.fetchFrom(params);
+                        if (!imagesRoot.exists()) {
+                            imagesRoot.mkdirs();
+                        }
+                        return new File(imagesRoot, "win-exe.image");
+                    },
+                    (s, p) -> null);
+
+    private final static String EXE_WRAPPER_NAME = "msiwrapper.exe";
+
+    @Override
+    public String getName() {
+        return getString("exe.bundler.name");
+    }
+
+    @Override
+    public String getID() {
+        return "exe";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "INSTALLER";
+    }
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) throws PackagerException {
+        return bundle(params, outputParentDir);
+    }
+
+    @Override
+    public boolean supported(boolean platformInstaller) {
+        return msiBundler.supported(platformInstaller);
+    }
+
+    @Override
+    public boolean isDefault() {
+        return true;
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws ConfigException {
+        return msiBundler.validate(params);
+    }
+
+    public File bundle(Map<String, ? super Object> params, File outdir)
+            throws PackagerException {
+
+        IOUtils.writableOutputDir(outdir.toPath());
+
+        File exeImageDir = EXE_IMAGE_DIR.fetchFrom(params);
+
+        // Write msi to temporary directory.
+        File msi = msiBundler.bundle(params, exeImageDir);
+
+        try {
+            new ScriptRunner()
+            .setDirectory(msi.toPath().getParent())
+            .setResourceCategoryId("resource.post-msi-script")
+            .setScriptNameSuffix("post-msi")
+            .setEnvironmentVariable("JpMsiFile", msi.getAbsolutePath().toString())
+            .run(params);
+
+            return buildEXE(msi, outdir);
+        } catch (IOException ex) {
+            Log.verbose(ex);
+            throw new PackagerException(ex);
+        }
+    }
+
+    private File buildEXE(File msi, File outdir)
+            throws IOException {
+
+        Log.verbose(MessageFormat.format(
+                getString("message.outputting-to-location"),
+                outdir.getAbsolutePath()));
+
+        // Copy template msi wrapper next to msi file
+        String exePath = msi.getAbsolutePath();
+        exePath = exePath.substring(0, exePath.lastIndexOf('.')) + ".exe";
+        try (InputStream is = OverridableResource.readDefault(EXE_WRAPPER_NAME)) {
+            Files.copy(is, Path.of(exePath));
+        }
+        // Embed msi in msi wrapper exe.
+        embedMSI(exePath, msi.getAbsolutePath());
+
+        Path dstExePath = Paths.get(outdir.getAbsolutePath(),
+                Path.of(exePath).getFileName().toString());
+        Files.deleteIfExists(dstExePath);
+
+        Files.copy(Path.of(exePath), dstExePath);
+
+        Log.verbose(MessageFormat.format(
+                getString("message.output-location"),
+                outdir.getAbsolutePath()));
+
+        return dstExePath.toFile();
+    }
+
+    private static String getString(String key)
+            throws MissingResourceException {
+        return I18N.getString(key);
+    }
+
+    private final WinMsiBundler msiBundler = new WinMsiBundler();
+
+    private static native int embedMSI(String exePath, String msiPath);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,580 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+import static jdk.incubator.jpackage.internal.WindowsBundlerParam.*;
+
+/**
+ * WinMsiBundler
+ *
+ * Produces .msi installer from application image. Uses WiX Toolkit to build
+ * .msi installer.
+ * <p>
+ * {@link #execute} method creates a number of source files with the description
+ * of installer to be processed by WiX tools. Generated source files are stored
+ * in "config" subdirectory next to "app" subdirectory in the root work
+ * directory. The following WiX source files are generated:
+ * <ul>
+ * <li>main.wxs. Main source file with the installer description
+ * <li>bundle.wxf. Source file with application and Java run-time directory tree
+ * description.
+ * </ul>
+ * <p>
+ * main.wxs file is a copy of main.wxs resource from
+ * jdk.incubator.jpackage.internal.resources package. It is parametrized with the
+ * following WiX variables:
+ * <ul>
+ * <li>JpAppName. Name of the application. Set to the value of --name command
+ * line option
+ * <li>JpAppVersion. Version of the application. Set to the value of
+ * --app-version command line option
+ * <li>JpAppVendor. Vendor of the application. Set to the value of --vendor
+ * command line option
+ * <li>JpAppDescription. Description of the application. Set to the value of
+ * --description command line option
+ * <li>JpProductCode. Set to product code UUID of the application. Random value
+ * generated by jpackage every time {@link #execute} method is called
+ * <li>JpProductUpgradeCode. Set to upgrade code UUID of the application. Random
+ * value generated by jpackage every time {@link #execute} method is called if
+ * --win-upgrade-uuid command line option is not specified. Otherwise this
+ * 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>
+ */
+public class WinMsiBundler  extends AbstractBundler {
+
+    public static final BundlerParamInfo<WinAppBundler> APP_BUNDLER =
+            new WindowsBundlerParam<>(
+            "win.app.bundler",
+            WinAppBundler.class,
+            params -> new WinAppBundler(),
+            null);
+
+    public static final BundlerParamInfo<File> MSI_IMAGE_DIR =
+            new WindowsBundlerParam<>(
+            "win.msi.imageDir",
+            File.class,
+            params -> {
+                File imagesRoot = IMAGES_ROOT.fetchFrom(params);
+                if (!imagesRoot.exists()) imagesRoot.mkdirs();
+                return new File(imagesRoot, "win-msi.image");
+            },
+            (s, p) -> null);
+
+    public static final BundlerParamInfo<File> WIN_APP_IMAGE =
+            new WindowsBundlerParam<>(
+            "win.app.image",
+            File.class,
+            null,
+            (s, p) -> null);
+
+    public static final StandardBundlerParam<Boolean> MSI_SYSTEM_WIDE  =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.WIN_PER_USER_INSTALLATION.getId(),
+                    Boolean.class,
+                    params -> true, // MSIs default to system wide
+                    // valueOf(null) is false,
+                    // and we actually do want null
+                    (s, p) -> (s == null || "null".equalsIgnoreCase(s))? null
+                            : Boolean.valueOf(s)
+            );
+
+
+    public static final StandardBundlerParam<String> PRODUCT_VERSION =
+            new StandardBundlerParam<>(
+                    "win.msi.productVersion",
+                    String.class,
+                    VERSION::fetchFrom,
+                    (s, p) -> s
+            );
+
+    private static final BundlerParamInfo<String> UPGRADE_UUID =
+            new WindowsBundlerParam<>(
+            Arguments.CLIOptions.WIN_UPGRADE_UUID.getId(),
+            String.class,
+            null,
+            (s, p) -> s);
+
+    @Override
+    public String getName() {
+        return I18N.getString("msi.bundler.name");
+    }
+
+    @Override
+    public String getID() {
+        return "msi";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "INSTALLER";
+    }
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) throws PackagerException {
+        return bundle(params, outputParentDir);
+    }
+
+    @Override
+    public boolean supported(boolean platformInstaller) {
+        try {
+            if (wixToolset == null) {
+                wixToolset = WixTool.toolset();
+            }
+            return true;
+        } catch (ConfigException ce) {
+            Log.error(ce.getMessage());
+            if (ce.getAdvice() != null) {
+                Log.error(ce.getAdvice());
+            }
+        } catch (Exception e) {
+            Log.error(e.getMessage());
+        }
+        return false;
+    }
+
+    @Override
+    public boolean isDefault() {
+        return false;
+    }
+
+    private static UUID getUpgradeCode(Map<String, ? super Object> params) {
+        String upgradeCode = UPGRADE_UUID.fetchFrom(params);
+        if (upgradeCode != null) {
+            return UUID.fromString(upgradeCode);
+        }
+        return createNameUUID("UpgradeCode", params, List.of(VENDOR, APP_NAME));
+    }
+
+    private static UUID getProductCode(Map<String, ? super Object> params) {
+        return createNameUUID("ProductCode", params, List.of(VENDOR, APP_NAME,
+                VERSION));
+    }
+
+    private static UUID createNameUUID(String prefix,
+            Map<String, ? super Object> params,
+            List<StandardBundlerParam<String>> components) {
+        String key = Stream.concat(Stream.of(prefix), components.stream().map(
+                c -> c.fetchFrom(params))).collect(Collectors.joining("/"));
+        return UUID.nameUUIDFromBytes(key.getBytes(StandardCharsets.UTF_8));
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws ConfigException {
+        try {
+            if (wixToolset == null) {
+                wixToolset = WixTool.toolset();
+            }
+
+            try {
+                getUpgradeCode(params);
+            } catch (IllegalArgumentException ex) {
+                throw new ConfigException(ex);
+            }
+
+            for (var toolInfo: wixToolset.values()) {
+                Log.verbose(MessageFormat.format(I18N.getString(
+                        "message.tool-version"), toolInfo.path.getFileName(),
+                        toolInfo.version));
+            }
+
+            wixSourcesBuilder.setWixVersion(wixToolset.get(WixTool.Light).version);
+
+            wixSourcesBuilder.logWixFeatures();
+
+            /********* validate bundle parameters *************/
+
+            String version = PRODUCT_VERSION.fetchFrom(params);
+            if (!isVersionStringValid(version)) {
+                throw new ConfigException(
+                        MessageFormat.format(I18N.getString(
+                                "error.version-string-wrong-format"), version),
+                        MessageFormat.format(I18N.getString(
+                                "error.version-string-wrong-format.advice"),
+                                PRODUCT_VERSION.getID()));
+            }
+
+            // only one mime type per association, at least one file extension
+            List<Map<String, ? super Object>> associations =
+                    FILE_ASSOCIATIONS.fetchFrom(params);
+            if (associations != null) {
+                for (int i = 0; i < associations.size(); i++) {
+                    Map<String, ? super Object> assoc = associations.get(i);
+                    List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc);
+                    if (mimes.size() > 1) {
+                        throw new ConfigException(MessageFormat.format(
+                                I18N.getString("error.too-many-content-types-for-file-association"), i),
+                                I18N.getString("error.too-many-content-types-for-file-association.advice"));
+                    }
+                }
+            }
+
+            return true;
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    // https://msdn.microsoft.com/en-us/library/aa370859%28v=VS.85%29.aspx
+    // The format of the string is as follows:
+    //     major.minor.build
+    // The first field is the major version and has a maximum value of 255.
+    // The second field is the minor version and has a maximum value of 255.
+    // The third field is called the build version or the update version and
+    // has a maximum value of 65,535.
+    static boolean isVersionStringValid(String v) {
+        if (v == null) {
+            return true;
+        }
+
+        String p[] = v.split("\\.");
+        if (p.length > 3) {
+            Log.verbose(I18N.getString(
+                    "message.version-string-too-many-components"));
+            return false;
+        }
+
+        try {
+            int val = Integer.parseInt(p[0]);
+            if (val < 0 || val > 255) {
+                Log.verbose(I18N.getString(
+                        "error.version-string-major-out-of-range"));
+                return false;
+            }
+            if (p.length > 1) {
+                val = Integer.parseInt(p[1]);
+                if (val < 0 || val > 255) {
+                    Log.verbose(I18N.getString(
+                            "error.version-string-minor-out-of-range"));
+                    return false;
+                }
+            }
+            if (p.length > 2) {
+                val = Integer.parseInt(p[2]);
+                if (val < 0 || val > 65535) {
+                    Log.verbose(I18N.getString(
+                            "error.version-string-build-out-of-range"));
+                    return false;
+                }
+            }
+        } catch (NumberFormatException ne) {
+            Log.verbose(I18N.getString("error.version-string-part-not-number"));
+            Log.verbose(ne);
+            return false;
+        }
+
+        return true;
+    }
+
+    private void prepareProto(Map<String, ? super Object> params)
+                throws PackagerException, IOException {
+        File appImage = StandardBundlerParam.getPredefinedAppImage(params);
+        File appDir = null;
+
+        // we either have an application image or need to build one
+        if (appImage != null) {
+            appDir = new File(MSI_IMAGE_DIR.fetchFrom(params),
+                    APP_NAME.fetchFrom(params));
+            // copy everything from appImage dir into appDir/name
+            IOUtils.copyRecursive(appImage.toPath(), appDir.toPath());
+        } else {
+            appDir = APP_BUNDLER.fetchFrom(params).doBundle(params,
+                    MSI_IMAGE_DIR.fetchFrom(params), true);
+        }
+
+        params.put(WIN_APP_IMAGE.getID(), appDir);
+
+        String licenseFile = LICENSE_FILE.fetchFrom(params);
+        if (licenseFile != null) {
+            // need to copy license file to the working directory
+            // and convert to rtf if needed
+            File lfile = new File(licenseFile);
+            File destFile = new File(CONFIG_ROOT.fetchFrom(params),
+                    lfile.getName());
+
+            IOUtils.copyFile(lfile, destFile);
+            destFile.setWritable(true);
+            ensureByMutationFileIsRTF(destFile);
+        }
+    }
+
+    public File bundle(Map<String, ? super Object> params, File outdir)
+            throws PackagerException {
+
+        IOUtils.writableOutputDir(outdir.toPath());
+
+        Path imageDir = MSI_IMAGE_DIR.fetchFrom(params).toPath();
+        try {
+            Files.createDirectories(imageDir);
+
+            prepareProto(params);
+
+            wixSourcesBuilder
+            .initFromParams(WIN_APP_IMAGE.fetchFrom(params).toPath(), params)
+            .createMainFragment(CONFIG_ROOT.fetchFrom(params).toPath().resolve(
+                    "bundle.wxf"));
+
+            Map<String, String> wixVars = prepareMainProjectFile(params);
+
+            new ScriptRunner()
+            .setDirectory(imageDir)
+            .setResourceCategoryId("resource.post-app-image-script")
+            .setScriptNameSuffix("post-image")
+            .setEnvironmentVariable("JpAppImageDir", imageDir.toAbsolutePath().toString())
+            .run(params);
+
+            return buildMSI(params, wixVars, outdir);
+        } catch (IOException ex) {
+            Log.verbose(ex);
+            throw new PackagerException(ex);
+        }
+    }
+
+    Map<String, String> prepareMainProjectFile(
+            Map<String, ? super Object> params) throws IOException {
+        Map<String, String> data = new HashMap<>();
+
+        final UUID productCode = getProductCode(params);
+        final UUID upgradeCode = getUpgradeCode(params);
+
+        data.put("JpProductCode", productCode.toString());
+        data.put("JpProductUpgradeCode", upgradeCode.toString());
+
+        Log.verbose(MessageFormat.format(I18N.getString("message.product-code"),
+                productCode));
+        Log.verbose(MessageFormat.format(I18N.getString("message.upgrade-code"),
+                upgradeCode));
+
+        data.put("JpAllowUpgrades", "yes");
+
+        data.put("JpAppName", APP_NAME.fetchFrom(params));
+        data.put("JpAppDescription", DESCRIPTION.fetchFrom(params));
+        data.put("JpAppVendor", VENDOR.fetchFrom(params));
+        data.put("JpAppVersion", PRODUCT_VERSION.fetchFrom(params));
+
+        final Path configDir = CONFIG_ROOT.fetchFrom(params).toPath();
+
+        data.put("JpConfigDir", configDir.toAbsolutePath().toString());
+
+        if (MSI_SYSTEM_WIDE.fetchFrom(params)) {
+            data.put("JpIsSystemWide", "yes");
+        }
+
+        String licenseFile = LICENSE_FILE.fetchFrom(params);
+        if (licenseFile != null) {
+            String lname = new File(licenseFile).getName();
+            File destFile = new File(CONFIG_ROOT.fetchFrom(params), lname);
+            data.put("JpLicenseRtf", destFile.getAbsolutePath());
+        }
+
+        // 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, Paths.get(
+                        CONFIG_ROOT.fetchFrom(params).getAbsolutePath(),
+                        fname));
+            }
+        }
+
+        // Copy l10n files.
+        for (String loc : Arrays.asList("en", "ja", "zh_CN")) {
+            String fname = "MsiInstallerStrings_" + loc + ".wxl";
+            try (InputStream is = OverridableResource.readDefault(fname)) {
+                Files.copy(is, Paths.get(
+                        CONFIG_ROOT.fetchFrom(params).getAbsolutePath(),
+                        fname));
+            }
+        }
+
+        createResource("main.wxs", params)
+                .setCategory(I18N.getString("resource.main-wix-file"))
+                .saveToFile(configDir.resolve("main.wxs"));
+
+        createResource("overrides.wxi", params)
+                .setCategory(I18N.getString("resource.overrides-wix-file"))
+                .saveToFile(configDir.resolve("overrides.wxi"));
+
+        return data;
+    }
+
+    private File buildMSI(Map<String, ? super Object> params,
+            Map<String, String> wixVars, File outdir)
+            throws IOException {
+
+        File msiOut = new File(
+                outdir, INSTALLER_FILE_NAME.fetchFrom(params) + ".msi");
+
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.preparing-msi-config"), msiOut.getAbsolutePath()));
+
+        WixPipeline wixPipeline = new WixPipeline()
+        .setToolset(wixToolset.entrySet().stream().collect(
+                Collectors.toMap(
+                        entry -> entry.getKey(),
+                        entry -> entry.getValue().path)))
+        .setWixObjDir(TEMP_ROOT.fetchFrom(params).toPath().resolve("wixobj"))
+        .setWorkDir(WIN_APP_IMAGE.fetchFrom(params).toPath())
+        .addSource(CONFIG_ROOT.fetchFrom(params).toPath().resolve("main.wxs"), wixVars)
+        .addSource(CONFIG_ROOT.fetchFrom(params).toPath().resolve("bundle.wxf"), null);
+
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.generating-msi"), msiOut.getAbsolutePath()));
+
+        boolean enableLicenseUI = (LICENSE_FILE.fetchFrom(params) != null);
+        boolean enableInstalldirUI = INSTALLDIR_CHOOSER.fetchFrom(params);
+
+        List<String> lightArgs = new ArrayList<>();
+
+        if (!MSI_SYSTEM_WIDE.fetchFrom(params)) {
+            wixPipeline.addLightOptions("-sice:ICE91");
+        }
+        if (enableLicenseUI || enableInstalldirUI) {
+            wixPipeline.addLightOptions("-ext", "WixUIExtension");
+        }
+
+        wixPipeline.addLightOptions("-loc",
+                CONFIG_ROOT.fetchFrom(params).toPath().resolve(I18N.getString(
+                        "resource.wxl-file-name")).toAbsolutePath().toString());
+
+        // Only needed if we using CA dll, so Wix can find it
+        if (enableInstalldirUI) {
+            wixPipeline.addLightOptions("-b", CONFIG_ROOT.fetchFrom(params).getAbsolutePath());
+        }
+
+        wixPipeline.buildMsi(msiOut.toPath().toAbsolutePath());
+
+        return msiOut;
+    }
+
+    public static void ensureByMutationFileIsRTF(File f) {
+        if (f == null || !f.isFile()) return;
+
+        try {
+            boolean existingLicenseIsRTF = false;
+
+            try (FileInputStream fin = new FileInputStream(f)) {
+                byte[] firstBits = new byte[7];
+
+                if (fin.read(firstBits) == firstBits.length) {
+                    String header = new String(firstBits);
+                    existingLicenseIsRTF = "{\\rtf1\\".equals(header);
+                }
+            }
+
+            if (!existingLicenseIsRTF) {
+                List<String> oldLicense = Files.readAllLines(f.toPath());
+                try (Writer w = Files.newBufferedWriter(
+                        f.toPath(), Charset.forName("Windows-1252"))) {
+                    w.write("{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033"
+                            + "{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}}\n"
+                            + "\\viewkind4\\uc1\\pard\\sa200\\sl276"
+                            + "\\slmult1\\lang9\\fs20 ");
+                    oldLicense.forEach(l -> {
+                        try {
+                            for (char c : l.toCharArray()) {
+                                // 0x00 <= ch < 0x20 Escaped (\'hh)
+                                // 0x20 <= ch < 0x80 Raw(non - escaped) char
+                                // 0x80 <= ch <= 0xFF Escaped(\ 'hh)
+                                // 0x5C, 0x7B, 0x7D (special RTF characters
+                                // \,{,})Escaped(\'hh)
+                                // ch > 0xff Escaped (\\ud###?)
+                                if (c < 0x10) {
+                                    w.write("\\'0");
+                                    w.write(Integer.toHexString(c));
+                                } else if (c > 0xff) {
+                                    w.write("\\ud");
+                                    w.write(Integer.toString(c));
+                                    // \\uc1 is in the header and in effect
+                                    // so we trail with a replacement char if
+                                    // the font lacks that character - '?'
+                                    w.write("?");
+                                } else if ((c < 0x20) || (c >= 0x80) ||
+                                        (c == 0x5C) || (c == 0x7B) ||
+                                        (c == 0x7D)) {
+                                    w.write("\\'");
+                                    w.write(Integer.toHexString(c));
+                                } else {
+                                    w.write(c);
+                                }
+                            }
+                            // blank lines are interpreted as paragraph breaks
+                            if (l.length() < 1) {
+                                w.write("\\par");
+                            } else {
+                                w.write(" ");
+                            }
+                            w.write("\r\n");
+                        } catch (IOException e) {
+                            Log.verbose(e);
+                        }
+                    });
+                    w.write("}\r\n");
+                }
+            }
+        } catch (IOException e) {
+            Log.verbose(e);
+        }
+
+    }
+
+    private Map<WixTool, WixTool.ToolInfo> wixToolset;
+    private WixSourcesBuilder wixSourcesBuilder = new WixSourcesBuilder();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsAppImageBuilder.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2015, 2019, 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.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.PosixFilePermission;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
+
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+
+public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
+
+    static {
+        System.loadLibrary("jpackage");
+    }
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.WinResources");
+
+    private final static String LIBRARY_NAME = "applauncher.dll";
+    private final static String REDIST_MSVCR = "vcruntimeVS_VER.dll";
+    private final static String REDIST_MSVCP = "msvcpVS_VER.dll";
+
+    private final static String TEMPLATE_APP_ICON ="java48.ico";
+
+    private static final String EXECUTABLE_PROPERTIES_TEMPLATE =
+            "WinLauncher.template";
+
+    private final Path root;
+    private final Path appDir;
+    private final Path appModsDir;
+    private final Path runtimeDir;
+    private final Path mdir;
+    private final Path binDir;
+
+    public static final BundlerParamInfo<Boolean> REBRAND_EXECUTABLE =
+            new WindowsBundlerParam<>(
+            "win.launcher.rebrand",
+            Boolean.class,
+            params -> Boolean.TRUE,
+            (s, p) -> Boolean.valueOf(s));
+
+    public static final BundlerParamInfo<File> ICON_ICO =
+            new StandardBundlerParam<>(
+            "icon.ico",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".ico")) {
+                    Log.error(MessageFormat.format(
+                            I18N.getString("message.icon-not-ico"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+    public static final StandardBundlerParam<Boolean> CONSOLE_HINT =
+            new WindowsBundlerParam<>(
+            Arguments.CLIOptions.WIN_CONSOLE_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));
+
+    public WindowsAppImageBuilder(Map<String, Object> params, Path imageOutDir)
+            throws IOException {
+        super(params,
+                imageOutDir.resolve(APP_NAME.fetchFrom(params) + "/runtime"));
+
+        Objects.requireNonNull(imageOutDir);
+
+        this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params));
+        this.appDir = root.resolve("app");
+        this.appModsDir = appDir.resolve("mods");
+        this.runtimeDir = root.resolve("runtime");
+        this.mdir = runtimeDir.resolve("lib");
+        this.binDir = root;
+        Files.createDirectories(appDir);
+        Files.createDirectories(runtimeDir);
+    }
+
+    private void writeEntry(InputStream in, Path dstFile) throws IOException {
+        Files.createDirectories(dstFile.getParent());
+        Files.copy(in, dstFile);
+    }
+
+    private static String getLauncherName(Map<String, ? super Object> params) {
+        return APP_NAME.fetchFrom(params) + ".exe";
+    }
+
+    // Returns launcher resource name for launcher we need to use.
+    public static String getLauncherResourceName(
+            Map<String, ? super Object> params) {
+        if (CONSOLE_HINT.fetchFrom(params)) {
+            return "jpackageapplauncher.exe";
+        } else {
+            return "jpackageapplauncherw.exe";
+        }
+    }
+
+    public static String getLauncherCfgName(
+            Map<String, ? super Object> params) {
+        return "app/" + APP_NAME.fetchFrom(params) +".cfg";
+    }
+
+    private File getConfig_AppIcon(Map<String, ? super Object> params) {
+        return new File(getConfigRoot(params),
+                APP_NAME.fetchFrom(params) + ".ico");
+    }
+
+    private File getConfig_ExecutableProperties(
+           Map<String, ? super Object> params) {
+        return new File(getConfigRoot(params),
+                APP_NAME.fetchFrom(params) + ".properties");
+    }
+
+    File getConfigRoot(Map<String, ? super Object> params) {
+        return CONFIG_ROOT.fetchFrom(params);
+    }
+
+    @Override
+    public Path getAppDir() {
+        return appDir;
+    }
+
+    @Override
+    public Path getAppModsDir() {
+        return appModsDir;
+    }
+
+    @Override
+    public void prepareApplicationFiles(Map<String, ? super Object> params)
+            throws IOException {
+        Map<String, ? super Object> originalParams = new HashMap<>(params);
+
+        try {
+            IOUtils.writableOutputDir(root);
+            IOUtils.writableOutputDir(binDir);
+        } catch (PackagerException pe) {
+            throw new RuntimeException(pe);
+        }
+        AppImageFile.save(root, params);
+
+        // create the .exe launchers
+        createLauncherForEntryPoint(params);
+
+        // copy the jars
+        copyApplication(params);
+
+        // copy in the needed libraries
+        try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
+            Files.copy(is_lib, binDir.resolve(LIBRARY_NAME));
+        }
+
+        copyMSVCDLLs();
+
+        // create the additional launcher(s), if any
+        List<Map<String, ? super Object>> entryPoints =
+                StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
+        for (Map<String, ? super Object> entryPoint : entryPoints) {
+            createLauncherForEntryPoint(
+                    AddLauncherArguments.merge(originalParams, entryPoint));
+        }
+    }
+
+    @Override
+    public void prepareJreFiles(Map<String, ? super Object> params)
+        throws IOException {}
+
+    private void copyMSVCDLLs() throws IOException {
+        AtomicReference<IOException> ioe = new AtomicReference<>();
+        try (Stream<Path> files = Files.list(runtimeDir.resolve("bin"))) {
+            files.filter(p -> Pattern.matches(
+                    "^(vcruntime|msvcp|msvcr|ucrtbase|api-ms-win-).*\\.dll$",
+                    p.toFile().getName().toLowerCase()))
+                 .forEach(p -> {
+                    try {
+                        Files.copy(p, binDir.resolve((p.toFile().getName())));
+                    } catch (IOException e) {
+                        ioe.set(e);
+                    }
+                });
+        }
+
+        IOException e = ioe.get();
+        if (e != null) {
+            throw e;
+        }
+    }
+
+    private void validateValueAndPut(
+            Map<String, String> data, String key,
+            BundlerParamInfo<String> param,
+            Map<String, ? super Object> params) {
+        String value = param.fetchFrom(params);
+        if (value.contains("\r") || value.contains("\n")) {
+            Log.error("Configuration Parameter " + param.getID()
+                    + " contains multiple lines of text, ignore it");
+            data.put(key, "");
+            return;
+        }
+        data.put(key, value);
+    }
+
+    protected void prepareExecutableProperties(
+           Map<String, ? super Object> params) throws IOException {
+
+        Map<String, String> data = new HashMap<>();
+
+        // mapping Java parameters in strings for version resource
+        validateValueAndPut(data, "COMPANY_NAME", VENDOR, params);
+        validateValueAndPut(data, "FILE_DESCRIPTION", DESCRIPTION, params);
+        validateValueAndPut(data, "FILE_VERSION", VERSION, params);
+        data.put("INTERNAL_NAME", getLauncherName(params));
+        validateValueAndPut(data, "LEGAL_COPYRIGHT", COPYRIGHT, params);
+        data.put("ORIGINAL_FILENAME", getLauncherName(params));
+        validateValueAndPut(data, "PRODUCT_NAME", APP_NAME, params);
+        validateValueAndPut(data, "PRODUCT_VERSION", VERSION, params);
+
+        createResource(EXECUTABLE_PROPERTIES_TEMPLATE, params)
+                .setCategory(I18N.getString("resource.executable-properties-template"))
+                .setSubstitutionData(data)
+                .saveToFile(getConfig_ExecutableProperties(params));
+    }
+
+    private void createLauncherForEntryPoint(
+            Map<String, ? super Object> params) throws IOException {
+
+        File iconTarget = getConfig_AppIcon(params);
+
+        createResource(TEMPLATE_APP_ICON, params)
+                .setCategory("icon")
+                .setExternal(ICON_ICO.fetchFrom(params))
+                .saveToFile(iconTarget);
+
+        writeCfgFile(params, root.resolve(
+                getLauncherCfgName(params)).toFile());
+
+        prepareExecutableProperties(params);
+
+        // Copy executable to bin folder
+        Path executableFile = binDir.resolve(getLauncherName(params));
+
+        try (InputStream is_launcher =
+                getResourceAsStream(getLauncherResourceName(params))) {
+            writeEntry(is_launcher, executableFile);
+        }
+
+        File launcher = executableFile.toFile();
+        launcher.setWritable(true, true);
+
+        // Update branding of EXE file
+        if (REBRAND_EXECUTABLE.fetchFrom(params)) {
+            try {
+                String tempDirectory = WindowsDefender.getUserTempDirectory();
+                if (Arguments.CLIOptions.context().userProvidedBuildRoot) {
+                    tempDirectory =
+                            TEMP_ROOT.fetchFrom(params).getAbsolutePath();
+                }
+                if (WindowsDefender.isThereAPotentialWindowsDefenderIssue(
+                        tempDirectory)) {
+                    Log.verbose(MessageFormat.format(I18N.getString(
+                            "message.potential.windows.defender.issue"),
+                            tempDirectory));
+                }
+
+                launcher.setWritable(true);
+
+                if (iconTarget.exists()) {
+                    iconSwap(iconTarget.getAbsolutePath(),
+                            launcher.getAbsolutePath());
+                }
+
+                File executableProperties =
+                        getConfig_ExecutableProperties(params);
+
+                if (executableProperties.exists()) {
+                    if (versionSwap(executableProperties.getAbsolutePath(),
+                            launcher.getAbsolutePath()) != 0) {
+                        throw new RuntimeException(MessageFormat.format(
+                                I18N.getString("error.version-swap"),
+                                executableProperties.getAbsolutePath()));
+                    }
+                }
+            } finally {
+                executableFile.toFile().setExecutable(true);
+                executableFile.toFile().setReadOnly();
+            }
+        }
+
+        Files.copy(iconTarget.toPath(),
+                binDir.resolve(APP_NAME.fetchFrom(params) + ".ico"));
+    }
+
+    private void copyApplication(Map<String, ? super Object> params)
+            throws IOException {
+        List<RelativeFileSet> appResourcesList =
+                APP_RESOURCES_LIST.fetchFrom(params);
+        if (appResourcesList == null) {
+            throw new RuntimeException("Null app resources?");
+        }
+        for (RelativeFileSet appResources : appResourcesList) {
+            if (appResources == null) {
+                throw new RuntimeException("Null app resources?");
+            }
+            File srcdir = appResources.getBaseDirectory();
+            for (String fname : appResources.getIncludedFiles()) {
+                copyEntry(appDir, srcdir, fname);
+            }
+        }
+    }
+
+    private static native int iconSwap(String iconTarget, String launcher);
+
+    private static native int versionSwap(String executableProperties,
+            String launcher);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsBundlerParam.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014, 2019, 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.incubator.jpackage.internal;
+
+import java.text.MessageFormat;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+class WindowsBundlerParam<T> extends StandardBundlerParam<T> {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.incubator.jpackage.internal.resources.WinResources");
+
+    WindowsBundlerParam(String id, Class<T> valueType,
+            Function<Map<String, ? super Object>, T> defaultValueFunction,
+            BiFunction<String,
+            Map<String, ? super Object>, T> stringConverter) {
+        super(id, valueType, defaultValueFunction, stringConverter);
+    }
+
+    static final BundlerParamInfo<String> INSTALLER_FILE_NAME =
+            new StandardBundlerParam<> (
+            "win.installerName",
+            String.class,
+            params -> {
+                String nm = APP_NAME.fetchFrom(params);
+                if (nm == null) return null;
+
+                String version = VERSION.fetchFrom(params);
+                if (version == null) {
+                    return nm;
+                } else {
+                    return nm + "-" + version;
+                }
+            },
+            (s, p) -> s);
+
+    static final StandardBundlerParam<String> MENU_GROUP =
+            new StandardBundlerParam<>(
+                    Arguments.CLIOptions.WIN_MENU_GROUP.getId(),
+                    String.class,
+                    params -> I18N.getString("param.menu-group.default"),
+                    (s, p) -> s
+            );
+
+    static final BundlerParamInfo<Boolean> INSTALLDIR_CHOOSER =
+            new StandardBundlerParam<> (
+            Arguments.CLIOptions.WIN_DIR_CHOOSER.getId(),
+            Boolean.class,
+            params -> Boolean.FALSE,
+            (s, p) -> Boolean.valueOf(s)
+    );
+
+    static final BundlerParamInfo<String> WINDOWS_INSTALL_DIR =
+            new StandardBundlerParam<>(
+            "windows-install-dir",
+            String.class,
+            params -> {
+                 String dir = INSTALL_DIR.fetchFrom(params);
+                 if (dir != null) {
+                     if (dir.contains(":") || dir.contains("..")) {
+                         Log.error(MessageFormat.format(I18N.getString(
+                                "message.invalid.install.dir"), dir,
+                                APP_NAME.fetchFrom(params)));
+                     } else {
+                        if (dir.startsWith("\\")) {
+                             dir = dir.substring(1);
+                        }
+                        if (dir.endsWith("\\")) {
+                             dir = dir.substring(0, dir.length() - 1);
+                        }
+                        return dir;
+                     }
+                 }
+                 return APP_NAME.fetchFrom(params); // Default to app name
+             },
+            (s, p) -> s
+    );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsDefender.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.util.List;
+
+final class WindowsDefender {
+
+    private WindowsDefender() {}
+
+    static final boolean isThereAPotentialWindowsDefenderIssue(String dir) {
+        boolean result = false;
+
+        if (Platform.getPlatform() == Platform.WINDOWS &&
+            Platform.getMajorVersion() == 10) {
+
+            // If DisableRealtimeMonitoring is not enabled then there
+            // may be a problem.
+            if (!WindowsRegistry.readDisableRealtimeMonitoring() &&
+                !isDirectoryInExclusionPath(dir)) {
+                result = true;
+            }
+        }
+
+        return result;
+    }
+
+    private static boolean isDirectoryInExclusionPath(String dir) {
+        boolean result = false;
+        // If the user temp directory is not found in the exclusion
+        // list then there may be a problem.
+        List<String> paths = WindowsRegistry.readExclusionsPaths();
+        for (String s : paths) {
+            if (WindowsRegistry.comparePaths(s, dir)) {
+                result = true;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    static final String getUserTempDirectory() {
+        String tempDirectory = System.getProperty("java.io.tmpdir");
+        return tempDirectory;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsRegistry.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, 2019, 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.incubator.jpackage.internal;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+final class WindowsRegistry {
+
+    // Currently we only support HKEY_LOCAL_MACHINE. Native implementation will
+    // require support for additinal HKEY if needed.
+    private static final int HKEY_LOCAL_MACHINE = 1;
+
+    static {
+        System.loadLibrary("jpackage");
+    }
+
+    private WindowsRegistry() {}
+
+    /**
+     * Reads the registry value for DisableRealtimeMonitoring.
+     * @return true if DisableRealtimeMonitoring is set to 0x1,
+     *         false otherwise.
+     */
+    static final boolean readDisableRealtimeMonitoring() {
+        final String subKey = "Software\\Microsoft\\"
+                  + "Windows Defender\\Real-Time Protection";
+        final String value = "DisableRealtimeMonitoring";
+        int result = readDwordValue(HKEY_LOCAL_MACHINE, subKey, value, 0);
+        return (result == 1);
+    }
+
+    static final List<String> readExclusionsPaths() {
+        List<String> result = new ArrayList<>();
+        final String subKey = "Software\\Microsoft\\"
+                + "Windows Defender\\Exclusions\\Paths";
+        long lKey = openRegistryKey(HKEY_LOCAL_MACHINE, subKey);
+        if (lKey == 0) {
+            return result;
+        }
+
+        String valueName;
+        int index = 0;
+        do {
+            valueName = enumRegistryValue(lKey, index);
+            if (valueName != null) {
+                result.add(valueName);
+                index++;
+            }
+        } while (valueName != null);
+
+        closeRegistryKey(lKey);
+
+        return result;
+    }
+
+    /**
+     * Reads DWORD registry value.
+     *
+     * @param key one of HKEY predefine value
+     * @param subKey registry sub key
+     * @param value value to read
+     * @param defaultValue default value in case if subKey or value not found
+     *                     or any other errors occurred
+     * @return value's data only if it was read successfully, otherwise
+     *         defaultValue
+     */
+    private static native int readDwordValue(int key, String subKey,
+            String value, int defaultValue);
+
+    /**
+     * Open registry key.
+     *
+     * @param key one of HKEY predefine value
+     * @param subKey registry sub key
+     * @return native handle to open key
+     */
+    private static native long openRegistryKey(int key, String subKey);
+
+    /**
+     * Enumerates the values for registry key.
+     *
+     * @param lKey native handle to open key returned by openRegistryKey
+     * @param index index of value starting from 0. Increment until this
+     *              function returns NULL which means no more values.
+     * @return returns value or NULL if error or no more data
+     */
+    private static native String enumRegistryValue(long lKey, int index);
+
+    /**
+     * Close registry key.
+     *
+     * @param lKey native handle to open key returned by openRegistryKey
+     */
+    private static native void closeRegistryKey(long lKey);
+
+    /**
+     * Compares two Windows paths regardless case and if paths
+     * are short or long.
+     *
+     * @param path1 path to compare
+     * @param path2 path to compare
+     * @return true if paths point to same location
+     */
+    public static native boolean comparePaths(String path1, String path2);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixPipeline.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.function.UnaryOperator;
+import java.util.stream.Stream;
+
+/**
+ * WiX pipeline. Compiles and links WiX sources.
+ */
+public class WixPipeline {
+    WixPipeline() {
+        sources = new ArrayList<>();
+        lightOptions = new ArrayList<>();
+    }
+
+    WixPipeline setToolset(Map<WixTool, Path> v) {
+        toolset = v;
+        return this;
+    }
+
+    WixPipeline setWixVariables(Map<String, String> v) {
+        wixVariables = v;
+        return this;
+    }
+
+    WixPipeline setWixObjDir(Path v) {
+        wixObjDir = v;
+        return this;
+    }
+
+    WixPipeline setWorkDir(Path v) {
+        workDir = v;
+        return this;
+    }
+
+    WixPipeline addSource(Path source, Map<String, String> wixVariables) {
+        WixSource entry = new WixSource();
+        entry.source = source;
+        entry.variables = wixVariables;
+        sources.add(entry);
+        return this;
+    }
+
+    WixPipeline addLightOptions(String ... v) {
+        lightOptions.addAll(List.of(v));
+        return this;
+    }
+
+    void buildMsi(Path msi) throws IOException {
+        List<Path> wixObjs = new ArrayList<>();
+        for (var source : sources) {
+            wixObjs.add(compile(source));
+        }
+
+        List<String> lightCmdline = new ArrayList<>(List.of(
+                toolset.get(WixTool.Light).toString(),
+                "-nologo",
+                "-spdb",
+                "-ext", "WixUtilExtension",
+                "-out", msi.toString()
+        ));
+
+        lightCmdline.addAll(lightOptions);
+        wixObjs.stream().map(Path::toString).forEach(lightCmdline::add);
+
+        Files.createDirectories(msi.getParent());
+        execute(lightCmdline);
+    }
+
+    private Path compile(WixSource wixSource) throws IOException {
+        UnaryOperator<Path> adjustPath = path -> {
+            return workDir != null ? path.toAbsolutePath() : path;
+        };
+
+        Path wixObj = adjustPath.apply(wixObjDir).resolve(IOUtils.replaceSuffix(
+                wixSource.source.getFileName(), ".wixobj"));
+
+        List<String> cmdline = new ArrayList<>(List.of(
+                toolset.get(WixTool.Candle).toString(),
+                "-nologo",
+                adjustPath.apply(wixSource.source).toString(),
+                "-ext", "WixUtilExtension",
+                "-arch", "x64",
+                "-out", wixObj.toAbsolutePath().toString()
+        ));
+
+        Map<String, String> appliedVaribales = new HashMap<>();
+        Stream.of(wixVariables, wixSource.variables)
+                .filter(Objects::nonNull)
+                .forEachOrdered(appliedVaribales::putAll);
+
+        appliedVaribales.entrySet().stream().map(wixVar -> String.format("-d%s=%s",
+                wixVar.getKey(), wixVar.getValue())).forEachOrdered(
+                cmdline::add);
+
+        execute(cmdline);
+
+        return wixObj;
+    }
+
+    private void execute(List<String> cmdline) throws IOException {
+        Executor.of(new ProcessBuilder(cmdline).directory(
+                workDir != null ? workDir.toFile() : null)).executeExpectSuccess();
+    }
+
+    private final static class WixSource {
+        Path source;
+        Map<String, String> variables;
+    }
+
+    private Map<WixTool, Path> toolset;
+    private Map<String, String> wixVariables;
+    private List<String> lightOptions;
+    private Path wixObjDir;
+    private Path workDir;
+    private List<WixSource> sources;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixSourcesBuilder.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,847 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.function.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import jdk.incubator.jpackage.internal.IOUtils.XmlConsumer;
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
+import static jdk.incubator.jpackage.internal.WinMsiBundler.*;
+import static jdk.incubator.jpackage.internal.WindowsBundlerParam.MENU_GROUP;
+import static jdk.incubator.jpackage.internal.WindowsBundlerParam.WINDOWS_INSTALL_DIR;
+
+/**
+ * Creates application WiX source files.
+ */
+class WixSourcesBuilder {
+
+    WixSourcesBuilder setWixVersion(DottedVersion v) {
+        wixVersion = v;
+        return this;
+    }
+
+    WixSourcesBuilder initFromParams(Path appImageRoot,
+            Map<String, ? super Object> params) {
+        Supplier<ApplicationLayout> appImageSupplier = () -> {
+            if (StandardBundlerParam.isRuntimeInstaller(params)) {
+                return ApplicationLayout.javaRuntime();
+            } else {
+                return ApplicationLayout.platformAppImage();
+            }
+        };
+
+        systemWide = MSI_SYSTEM_WIDE.fetchFrom(params);
+
+        registryKeyPath = Path.of("Software",
+                VENDOR.fetchFrom(params),
+                APP_NAME.fetchFrom(params),
+                VERSION.fetchFrom(params)).toString();
+
+        installDir = (systemWide ? PROGRAM_FILES : LOCAL_PROGRAM_FILES).resolve(
+                WINDOWS_INSTALL_DIR.fetchFrom(params));
+
+        do {
+            ApplicationLayout layout = appImageSupplier.get();
+            // Don't want AppImageFile.FILENAME in installed application.
+            // Register it with app image at a role without a match in installed
+            // app layout to exclude it from layout transformation.
+            layout.pathGroup().setPath(new Object(),
+                    AppImageFile.getPathInAppImage(Path.of("")));
+
+            // Want absolute paths to source files in generated WiX sources.
+            // This is to handle scenario if sources would be processed from
+            // differnt current directory.
+            appImage = layout.resolveAt(appImageRoot.toAbsolutePath().normalize());
+        } while (false);
+
+        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);
+        }
+
+        if (StandardBundlerParam.isRuntimeInstaller(params)) {
+            launcherPaths = Collections.emptyList();
+        } else {
+            launcherPaths = AppImageFile.getLauncherNames(appImageRoot, params).stream()
+                    .map(name -> installedAppImage.launchersDirectory().resolve(name))
+                    .map(WixSourcesBuilder::addExeSuffixToPath)
+                    .collect(Collectors.toList());
+        }
+
+        programMenuFolderName = MENU_GROUP.fetchFrom(params);
+
+        initFileAssociations(params);
+
+        return this;
+    }
+
+    void createMainFragment(Path file) 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>
+        });
+    }
+
+    void logWixFeatures() {
+        if (wixVersion.compareTo("3.6") >= 0) {
+            Log.verbose(MessageFormat.format(I18N.getString(
+                    "message.use-wix36-features"), wixVersion));
+        }
+    }
+
+    private void normalizeFileAssociation(FileAssociation fa) {
+        fa.launcherPath = addExeSuffixToPath(
+                installedAppImage.launchersDirectory().resolve(fa.launcherPath));
+
+        if (fa.iconPath != null && !fa.iconPath.toFile().exists()) {
+            fa.iconPath = null;
+        }
+
+        if (fa.iconPath != null) {
+            fa.iconPath = fa.iconPath.toAbsolutePath();
+        }
+
+        // Filter out empty extensions.
+        fa.extensions = fa.extensions.stream().filter(Predicate.not(
+                String::isEmpty)).collect(Collectors.toList());
+    }
+
+    private static Path addExeSuffixToPath(Path path) {
+        return IOUtils.addSuffix(path, ".exe");
+    }
+
+    private Path getInstalledFaIcoPath(FileAssociation fa) {
+        String fname = String.format("fa_%s.ico", String.join("_", fa.extensions));
+        return installedAppImage.destktopIntegrationDirectory().resolve(fname);
+    }
+
+    private void initFileAssociations(Map<String, ? super Object> params) {
+        associations = FileAssociation.fetchFrom(params).stream()
+                .peek(this::normalizeFileAssociation)
+                // Filter out file associations without extensions.
+                .filter(fa -> !fa.extensions.isEmpty())
+                .collect(Collectors.toList());
+
+        associations.stream().filter(fa -> fa.iconPath != null).forEach(fa -> {
+            // Need to add fa icon in the image.
+            Object key = new Object();
+            appImage.pathGroup().setPath(key, fa.iconPath);
+            installedAppImage.pathGroup().setPath(key, getInstalledFaIcoPath(fa));
+        });
+    }
+
+    private static UUID createNameUUID(String str) {
+        return UUID.nameUUIDFromBytes(str.getBytes(StandardCharsets.UTF_8));
+    }
+
+    private static UUID createNameUUID(Path path, String role) {
+        if (path.isAbsolute() || !ROOT_DIRS.contains(path.getName(0))) {
+            throw throwInvalidPathException(path);
+        }
+        // Paths are case insensitive on Windows
+        String keyPath = path.toString().toLowerCase();
+        if (role != null) {
+            keyPath = role + "@" + keyPath;
+        }
+        return createNameUUID(keyPath);
+    }
+
+    /**
+     * Value for Id attribute of various WiX elements.
+     */
+    enum Id {
+        File,
+        Folder("dir"),
+        Shortcut,
+        ProgId,
+        Icon,
+        CreateFolder("mkdir"),
+        RemoveFolder("rm");
+
+        Id() {
+            this.prefix = name().toLowerCase();
+        }
+
+        Id(String prefix) {
+            this.prefix = prefix;
+        }
+
+        String of(Path path) {
+            if (this == Folder && KNOWN_DIRS.contains(path)) {
+                return path.getFileName().toString();
+            }
+
+            String result = of(path, prefix, name());
+
+            if (this == Icon) {
+                // Icon id constructed from UUID value is too long and triggers
+                // CNDL1000 warning, so use Java hash code instead.
+                result = String.format("%s%d", prefix, result.hashCode()).replace(
+                        "-", "_");
+            }
+
+            return result;
+        }
+
+        private static String of(Path path, String prefix, String role) {
+            Objects.requireNonNull(role);
+            Objects.requireNonNull(prefix);
+            return String.format("%s%s", prefix,
+                    createNameUUID(path, role).toString().replace("-", ""));
+        }
+
+        static String of(Path path, String prefix) {
+            return of(path, prefix, prefix);
+        }
+
+        private final String prefix;
+    }
+
+    enum Component {
+        File(cfg().file()),
+        Shortcut(cfg().file().withRegistryKeyPath()),
+        ProgId(cfg().file().withRegistryKeyPath()),
+        CreateFolder(cfg().withRegistryKeyPath()),
+        RemoveFolder(cfg().withRegistryKeyPath());
+
+        Component() {
+            this.cfg = cfg();
+            this.id = Id.valueOf(name());
+        }
+
+        Component(Config cfg) {
+            this.cfg = cfg;
+            this.id = Id.valueOf(name());
+        }
+
+        UUID guidOf(Path path) {
+            return createNameUUID(path, name());
+        }
+
+        String idOf(Path path) {
+            return id.of(path);
+        }
+
+        boolean isRegistryKeyPath() {
+            return cfg.withRegistryKeyPath;
+        }
+
+        boolean isFile() {
+            return cfg.isFile;
+        }
+
+        static void startElement(XMLStreamWriter xml, String componentId,
+                String componentGuid) throws XMLStreamException, IOException {
+            xml.writeStartElement("Component");
+            xml.writeAttribute("Win64", "yes");
+            xml.writeAttribute("Id", componentId);
+            xml.writeAttribute("Guid", componentGuid);
+        }
+
+        private static final class Config {
+            Config withRegistryKeyPath() {
+                withRegistryKeyPath = true;
+                return this;
+            }
+
+            Config file() {
+                isFile = true;
+                return this;
+            }
+
+            private boolean isFile;
+            private boolean withRegistryKeyPath;
+        }
+
+        private static Config cfg() {
+            return new Config();
+        }
+
+        private final Config cfg;
+        private final Id id;
+    };
+
+    private static void addComponentGroup(XMLStreamWriter xml, String id,
+            List<String> componentIds) throws XMLStreamException, IOException {
+        xml.writeStartElement("ComponentGroup");
+        xml.writeAttribute("Id", id);
+        componentIds = componentIds.stream().filter(Objects::nonNull).collect(
+                Collectors.toList());
+        for (var componentId : componentIds) {
+            xml.writeStartElement("ComponentRef");
+            xml.writeAttribute("Id", componentId);
+            xml.writeEndElement();
+        }
+        xml.writeEndElement();
+    }
+
+    private String addComponent(XMLStreamWriter xml, Path path,
+            Component role, XmlConsumer xmlConsumer) throws XMLStreamException,
+            IOException {
+
+        final Path directoryRefPath;
+        if (role.isFile()) {
+            directoryRefPath = path.getParent();
+        } else {
+            directoryRefPath = path;
+        }
+
+        xml.writeStartElement("DirectoryRef");
+        xml.writeAttribute("Id", Id.Folder.of(directoryRefPath));
+
+        final String componentId = "c" + role.idOf(path);
+        Component.startElement(xml, componentId, String.format("{%s}",
+                role.guidOf(path)));
+
+        boolean isRegistryKeyPath = !systemWide || role.isRegistryKeyPath();
+        if (isRegistryKeyPath) {
+            addRegistryKeyPath(xml, directoryRefPath);
+            if ((role.isFile() || (role == Component.CreateFolder
+                    && !systemWide)) && !SYSTEM_DIRS.contains(directoryRefPath)) {
+                xml.writeStartElement("RemoveFolder");
+                int counter = Optional.ofNullable(removeFolderItems.get(
+                        directoryRefPath)).orElse(Integer.valueOf(0)).intValue() + 1;
+                removeFolderItems.put(directoryRefPath, counter);
+                xml.writeAttribute("Id", String.format("%s_%d", Id.RemoveFolder.of(
+                        directoryRefPath), counter));
+                xml.writeAttribute("On", "uninstall");
+                xml.writeEndElement();
+            }
+        }
+
+        xml.writeStartElement(role.name());
+        if (role != Component.CreateFolder) {
+            xml.writeAttribute("Id", role.idOf(path));
+        }
+
+        if (!isRegistryKeyPath) {
+            xml.writeAttribute("KeyPath", "yes");
+        }
+
+        xmlConsumer.accept(xml);
+        xml.writeEndElement();
+
+        xml.writeEndElement(); // <Component>
+        xml.writeEndElement(); // <DirectoryRef>
+
+        return componentId;
+    }
+
+    private void addFaComponentGroup(XMLStreamWriter xml)
+            throws XMLStreamException, IOException {
+
+        List<String> componentIds = new ArrayList<>();
+        for (var fa : associations) {
+            componentIds.addAll(addFaComponents(xml, fa));
+        }
+        addComponentGroup(xml, "FileAssociations", componentIds);
+    }
+
+    private void addShortcutComponentGroup(XMLStreamWriter xml) throws
+            XMLStreamException, IOException {
+        List<String> componentIds = new ArrayList<>();
+        Set<ShortcutsFolder> defineShortcutFolders = new HashSet<>();
+        for (var launcherPath : launcherPaths) {
+            for (var folder : shortcutFolders) {
+                String componentId = addShortcutComponent(xml, launcherPath,
+                        folder);
+                if (componentId != null) {
+                    defineShortcutFolders.add(folder);
+                    componentIds.add(componentId);
+                }
+            }
+        }
+
+        for (var folder : defineShortcutFolders) {
+            Path path = folder.getPath(this);
+            componentIds.addAll(addRootBranch(xml, path));
+        }
+
+        addComponentGroup(xml, "Shortcuts", componentIds);
+    }
+
+    private String addShortcutComponent(XMLStreamWriter xml, Path launcherPath,
+            ShortcutsFolder folder) throws XMLStreamException, IOException {
+        Objects.requireNonNull(folder);
+
+        if (!INSTALLDIR.equals(launcherPath.getName(0))) {
+            throw throwInvalidPathException(launcherPath);
+        }
+
+        String launcherBasename = IOUtils.replaceSuffix(
+                launcherPath.getFileName(), "").toString();
+
+        Path shortcutPath = folder.getPath(this).resolve(launcherBasename);
+        return addComponent(xml, shortcutPath, Component.Shortcut, unused -> {
+            final Path icoFile = IOUtils.addSuffix(
+                    installedAppImage.destktopIntegrationDirectory().resolve(
+                            launcherBasename), ".ico");
+
+            xml.writeAttribute("Name", launcherBasename);
+            xml.writeAttribute("WorkingDirectory", INSTALLDIR.toString());
+            xml.writeAttribute("Advertise", "no");
+            xml.writeAttribute("IconIndex", "0");
+            xml.writeAttribute("Target", String.format("[#%s]",
+                    Component.File.idOf(launcherPath)));
+            xml.writeAttribute("Icon", Id.Icon.of(icoFile));
+        });
+    }
+
+    private List<String> addFaComponents(XMLStreamWriter xml,
+            FileAssociation fa) throws XMLStreamException, IOException {
+        List<String> components = new ArrayList<>();
+        for (var extension: fa.extensions) {
+            Path path = INSTALLDIR.resolve(String.format("%s_%s", extension,
+                    fa.launcherPath.getFileName()));
+            components.add(addComponent(xml, path, Component.ProgId, unused -> {
+                xml.writeAttribute("Description", fa.description);
+
+                if (fa.iconPath != null) {
+                    xml.writeAttribute("Icon", Id.File.of(getInstalledFaIcoPath(
+                            fa)));
+                    xml.writeAttribute("IconIndex", "0");
+                }
+
+                xml.writeStartElement("Extension");
+                xml.writeAttribute("Id", extension);
+                xml.writeAttribute("Advertise", "no");
+
+                var mimeIt = fa.mimeTypes.iterator();
+                if (mimeIt.hasNext()) {
+                    String mime = mimeIt.next();
+                    xml.writeAttribute("ContentType", mime);
+
+                    if (!defaultedMimes.contains(mime)) {
+                        xml.writeStartElement("MIME");
+                        xml.writeAttribute("ContentType", mime);
+                        xml.writeAttribute("Default", "yes");
+                        xml.writeEndElement();
+                        defaultedMimes.add(mime);
+                    }
+                }
+
+                xml.writeStartElement("Verb");
+                xml.writeAttribute("Id", "open");
+                xml.writeAttribute("Command", "Open");
+                xml.writeAttribute("Argument", "%1");
+                xml.writeAttribute("TargetFile", Id.File.of(fa.launcherPath));
+                xml.writeEndElement(); // <Verb>
+
+                xml.writeEndElement(); // <Extension>
+            }));
+        }
+
+        return components;
+    }
+
+    private List<String> addRootBranch(XMLStreamWriter xml, Path path)
+            throws XMLStreamException, IOException {
+        if (!ROOT_DIRS.contains(path.getName(0))) {
+            throw throwInvalidPathException(path);
+        }
+
+        Function<Path, String> createDirectoryName = dir -> null;
+
+        boolean sysDir = true;
+        int levels = 1;
+        var dirIt = path.iterator();
+        xml.writeStartElement("DirectoryRef");
+        xml.writeAttribute("Id", dirIt.next().toString());
+
+        path = path.getName(0);
+        while (dirIt.hasNext()) {
+            levels++;
+            Path name = dirIt.next();
+            path = path.resolve(name);
+
+            if (sysDir && !SYSTEM_DIRS.contains(path)) {
+                sysDir = false;
+                createDirectoryName = dir -> dir.getFileName().toString();
+            }
+
+            final String directoryId;
+            if (!sysDir && path.equals(installDir)) {
+                directoryId = INSTALLDIR.toString();
+            } else {
+                directoryId = Id.Folder.of(path);
+            }
+            xml.writeStartElement("Directory");
+            xml.writeAttribute("Id", directoryId);
+
+            String directoryName = createDirectoryName.apply(path);
+            if (directoryName != null) {
+                xml.writeAttribute("Name", directoryName);
+            }
+        }
+
+        while (0 != levels--) {
+            xml.writeEndElement();
+        }
+
+        List<String> componentIds = new ArrayList<>();
+        while (!SYSTEM_DIRS.contains(path = path.getParent())) {
+            componentIds.add(addRemoveDirectoryComponent(xml, path));
+        }
+
+        return componentIds;
+    }
+
+    private String addRemoveDirectoryComponent(XMLStreamWriter xml, Path path)
+            throws XMLStreamException, IOException {
+        return addComponent(xml, path, Component.RemoveFolder,
+                unused -> xml.writeAttribute("On", "uninstall"));
+    }
+
+    private List<String> addDirectoryHierarchy(XMLStreamWriter xml)
+            throws XMLStreamException, IOException {
+
+        Set<Path> allDirs = new HashSet<>();
+        Set<Path> emptyDirs = new HashSet<>();
+        appImage.transform(installedAppImage, new PathGroup.TransformHandler() {
+            @Override
+            public void copyFile(Path src, Path dst) throws IOException {
+                Path dir = dst.getParent();
+                createDirectory(dir);
+                emptyDirs.remove(dir);
+            }
+
+            @Override
+            public void createDirectory(final Path dir) throws IOException {
+                if (!allDirs.contains(dir)) {
+                    emptyDirs.add(dir);
+                }
+
+                Path it = dir;
+                while (it != null && allDirs.add(it)) {
+                    it = it.getParent();
+                }
+
+                it = dir;
+                while ((it = it.getParent()) != null && emptyDirs.remove(it));
+            }
+        });
+
+        List<String> componentIds = new ArrayList<>();
+        for (var dir : emptyDirs) {
+            componentIds.add(addComponent(xml, dir, Component.CreateFolder,
+                    unused -> {}));
+        }
+
+        if (!systemWide) {
+            // Per-user install requires <RemoveFolder> component in every
+            // directory.
+            for (var dir : allDirs.stream()
+                    .filter(Predicate.not(emptyDirs::contains))
+                    .filter(Predicate.not(removeFolderItems::containsKey))
+                    .collect(Collectors.toList())) {
+                componentIds.add(addRemoveDirectoryComponent(xml, dir));
+            }
+        }
+
+        allDirs.remove(INSTALLDIR);
+        for (var dir : allDirs) {
+            xml.writeStartElement("DirectoryRef");
+            xml.writeAttribute("Id", Id.Folder.of(dir.getParent()));
+            xml.writeStartElement("Directory");
+            xml.writeAttribute("Id", Id.Folder.of(dir));
+            xml.writeAttribute("Name", dir.getFileName().toString());
+            xml.writeEndElement();
+            xml.writeEndElement();
+        }
+
+        componentIds.addAll(addRootBranch(xml, installDir));
+
+        return componentIds;
+    }
+
+    private void addFilesComponentGroup(XMLStreamWriter xml)
+            throws XMLStreamException, IOException {
+
+        List<Map.Entry<Path, Path>> files = new ArrayList<>();
+        appImage.transform(installedAppImage, new PathGroup.TransformHandler() {
+            @Override
+            public void copyFile(Path src, Path dst) throws IOException {
+                files.add(Map.entry(src, dst));
+            }
+
+            @Override
+            public void createDirectory(final Path dir) throws IOException {
+            }
+        });
+
+        List<String> componentIds = new ArrayList<>();
+        for (var file : files) {
+            Path src = file.getKey();
+            Path dst = file.getValue();
+
+            componentIds.add(addComponent(xml, dst, Component.File, unused -> {
+                xml.writeAttribute("Source", src.normalize().toString());
+                Path name = dst.getFileName();
+                if (!name.equals(src.getFileName())) {
+                    xml.writeAttribute("Name", name.toString());
+                }
+            }));
+        }
+
+        componentIds.addAll(addDirectoryHierarchy(xml));
+
+        componentIds.add(addDirectoryCleaner(xml, INSTALLDIR));
+
+        addComponentGroup(xml, "Files", componentIds);
+    }
+
+    private void addIconsFragment(XMLStreamWriter xml) throws
+            XMLStreamException, IOException {
+
+        PathGroup srcPathGroup = appImage.pathGroup();
+        PathGroup dstPathGroup = installedAppImage.pathGroup();
+
+        // Build list of copy operations for all .ico files in application image
+        List<Map.Entry<Path, Path>> icoFiles = new ArrayList<>();
+        srcPathGroup.transform(dstPathGroup, new PathGroup.TransformHandler() {
+            @Override
+            public void copyFile(Path src, Path dst) throws IOException {
+                if (src.getFileName().toString().endsWith(".ico")) {
+                    icoFiles.add(Map.entry(src, dst));
+                }
+            }
+
+            @Override
+            public void createDirectory(Path dst) throws IOException {
+            }
+        });
+
+        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
+            XMLStreamException, IOException {
+        addRegistryKeyPath(xml, path, () -> "ProductCode", () -> "[ProductCode]");
+    }
+
+    private void addRegistryKeyPath(XMLStreamWriter xml, Path path,
+            Supplier<String> nameAttr, Supplier<String> valueAttr) throws
+            XMLStreamException, IOException {
+
+        String regRoot = USER_PROFILE_DIRS.stream().anyMatch(path::startsWith)
+                || !systemWide ? "HKCU" : "HKLM";
+
+        xml.writeStartElement("RegistryKey");
+        xml.writeAttribute("Root", regRoot);
+        xml.writeAttribute("Key", registryKeyPath);
+        if (wixVersion.compareTo("3.6") < 0) {
+            xml.writeAttribute("Action", "createAndRemoveOnUninstall");
+        }
+        xml.writeStartElement("RegistryValue");
+        xml.writeAttribute("Type", "string");
+        xml.writeAttribute("KeyPath", "yes");
+        xml.writeAttribute("Name", nameAttr.get());
+        xml.writeAttribute("Value", valueAttr.get());
+        xml.writeEndElement(); // <RegistryValue>
+        xml.writeEndElement(); // <RegistryKey>
+    }
+
+    private String addDirectoryCleaner(XMLStreamWriter xml, Path path) throws
+            XMLStreamException, IOException {
+        if (wixVersion.compareTo("3.6") < 0) {
+            return null;
+        }
+
+        // rm -rf
+        final String baseId = Id.of(path, "rm_rf");
+        final String propertyId = baseId.toUpperCase();
+        final String componentId = ("c" + baseId);
+
+        xml.writeStartElement("Property");
+        xml.writeAttribute("Id", propertyId);
+        xml.writeStartElement("RegistrySearch");
+        xml.writeAttribute("Id", Id.of(path, "regsearch"));
+        xml.writeAttribute("Root", systemWide ? "HKLM" : "HKCU");
+        xml.writeAttribute("Key", registryKeyPath);
+        xml.writeAttribute("Type", "raw");
+        xml.writeAttribute("Name", propertyId);
+        xml.writeEndElement(); // <RegistrySearch>
+        xml.writeEndElement(); // <Property>
+
+        xml.writeStartElement("DirectoryRef");
+        xml.writeAttribute("Id", INSTALLDIR.toString());
+        Component.startElement(xml, componentId, "*");
+
+        addRegistryKeyPath(xml, INSTALLDIR, () -> propertyId, () -> {
+            // The following code converts a path to value to be saved in registry.
+            // E.g.:
+            //  INSTALLDIR -> [INSTALLDIR]
+            //  TERGETDIR/ProgramFiles64Folder/foo/bar -> [ProgramFiles64Folder]foo/bar
+            final Path rootDir = KNOWN_DIRS.stream()
+                    .sorted(Comparator.comparing(Path::getNameCount).reversed())
+                    .filter(path::startsWith)
+                    .findFirst().get();
+            StringBuilder sb = new StringBuilder();
+            sb.append(String.format("[%s]", rootDir.getFileName().toString()));
+            sb.append(rootDir.relativize(path).toString());
+            return sb.toString();
+        });
+
+        xml.writeStartElement(
+                "http://schemas.microsoft.com/wix/UtilExtension",
+                "RemoveFolderEx");
+        xml.writeAttribute("On", "uninstall");
+        xml.writeAttribute("Property", propertyId);
+        xml.writeEndElement(); // <RemoveFolderEx>
+        xml.writeEndElement(); // <Component>
+        xml.writeEndElement(); // <DirectoryRef>
+
+        return componentId;
+    }
+
+    private static IllegalArgumentException throwInvalidPathException(Path v) {
+        throw new IllegalArgumentException(String.format("Invalid path [%s]", v));
+    }
+
+    enum ShortcutsFolder {
+        ProgramMenu(PROGRAM_MENU_PATH),
+        Desktop(DESKTOP_PATH);
+
+        private ShortcutsFolder(Path root) {
+            this.root = root;
+        }
+
+        Path getPath(WixSourcesBuilder outer) {
+            if (this == ProgramMenu) {
+                return root.resolve(outer.programMenuFolderName);
+            }
+            return root;
+        }
+
+        private final Path root;
+    }
+
+    private DottedVersion wixVersion;
+
+    private boolean systemWide;
+
+    private String registryKeyPath;
+
+    private Path installDir;
+
+    private String programMenuFolderName;
+
+    private List<FileAssociation> associations;
+
+    private Set<ShortcutsFolder> shortcutFolders;
+
+    private List<Path> launcherPaths;
+
+    private ApplicationLayout appImage;
+    private ApplicationLayout installedAppImage;
+
+    private Map<Path, Integer> removeFolderItems;
+    private Set<String> defaultedMimes;
+
+    private final static Path TARGETDIR = Path.of("TARGETDIR");
+
+    private final static Path INSTALLDIR = Path.of("INSTALLDIR");
+
+    private final static Set<Path> ROOT_DIRS = Set.of(INSTALLDIR, TARGETDIR);
+
+    private final static Path PROGRAM_MENU_PATH = TARGETDIR.resolve("ProgramMenuFolder");
+
+    private final static Path DESKTOP_PATH = TARGETDIR.resolve("DesktopFolder");
+
+    private final static Path PROGRAM_FILES = TARGETDIR.resolve("ProgramFiles64Folder");
+
+    private final static Path LOCAL_PROGRAM_FILES = TARGETDIR.resolve("LocalAppDataFolder");
+
+    private final static Set<Path> SYSTEM_DIRS = Set.of(TARGETDIR,
+            PROGRAM_MENU_PATH, DESKTOP_PATH, PROGRAM_FILES, LOCAL_PROGRAM_FILES);
+
+    private final static Set<Path> KNOWN_DIRS = Stream.of(Set.of(INSTALLDIR),
+            SYSTEM_DIRS).flatMap(Set::stream).collect(
+            Collectors.toUnmodifiableSet());
+
+    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 WindowsBundlerParam<>(
+                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 WindowsBundlerParam<>(
+                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)
+        );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixTool.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * WiX tool.
+ */
+public enum WixTool {
+    Candle, Light;
+
+    static final class ToolInfo {
+        ToolInfo(Path path, String version) {
+            this.path = path;
+            this.version = new DottedVersion(version);
+        }
+
+        final Path path;
+        final DottedVersion version;
+    }
+
+    static Map<WixTool, ToolInfo> toolset() throws ConfigException {
+        Map<WixTool, ToolInfo> toolset = new HashMap<>();
+        for (var tool : values()) {
+            toolset.put(tool, tool.find());
+        }
+        return toolset;
+    }
+
+    ToolInfo find() throws ConfigException {
+        final Path toolFileName = IOUtils.addSuffix(
+                Path.of(name().toLowerCase()), ".exe");
+
+        String[] version = new String[1];
+        ConfigException reason = createToolValidator(toolFileName, version).get();
+        if (version[0] != null) {
+            if (reason == null) {
+                // Found in PATH.
+                return new ToolInfo(toolFileName, version[0]);
+            }
+
+            // Found in PATH, but something went wrong.
+            throw reason;
+        }
+
+        for (var dir : findWixInstallDirs()) {
+            Path path = dir.resolve(toolFileName);
+            if (path.toFile().exists()) {
+                reason = createToolValidator(path, version).get();
+                if (reason != null) {
+                    throw reason;
+                }
+                return new ToolInfo(path, version[0]);
+            }
+        }
+
+        throw reason;
+    }
+
+    private static Supplier<ConfigException> createToolValidator(Path toolPath,
+            String[] versionCtnr) {
+        return new ToolValidator(toolPath)
+                .setCommandLine("/?")
+                .setMinimalVersion(MINIMAL_VERSION)
+                .setToolNotFoundErrorHandler(
+                        (name, ex) -> new ConfigException(
+                                I18N.getString("error.no-wix-tools"),
+                                I18N.getString("error.no-wix-tools.advice")))
+                .setToolOldVersionErrorHandler(
+                        (name, version) -> new ConfigException(
+                                MessageFormat.format(I18N.getString(
+                                        "message.wrong-tool-version"), name,
+                                        version, MINIMAL_VERSION),
+                                I18N.getString("error.no-wix-tools.advice")))
+                .setVersionParser(output -> {
+                    versionCtnr[0] = "";
+                    String firstLineOfOutput = output.findFirst().orElse("");
+                    int separatorIdx = firstLineOfOutput.lastIndexOf(' ');
+                    if (separatorIdx == -1) {
+                        return null;
+                    }
+                    versionCtnr[0] = firstLineOfOutput.substring(separatorIdx + 1);
+                    return versionCtnr[0];
+                })::validate;
+    }
+
+    private final static DottedVersion MINIMAL_VERSION = DottedVersion.lazy("3.0");
+
+    static Path getSystemDir(String envVar, String knownDir) {
+        return Optional
+                .ofNullable(getEnvVariableAsPath(envVar))
+                .orElseGet(() -> Optional
+                        .ofNullable(getEnvVariableAsPath("SystemDrive"))
+                        .orElseGet(() -> Path.of("C:")).resolve(knownDir));
+    }
+
+    private static Path getEnvVariableAsPath(String envVar) {
+        String path = System.getenv(envVar);
+        if (path != null) {
+            try {
+                return Path.of(path);
+            } catch (InvalidPathException ex) {
+                Log.error(MessageFormat.format(I18N.getString(
+                        "error.invalid-envvar"), envVar));
+            }
+        }
+        return null;
+    }
+
+    private static List<Path> findWixInstallDirs() {
+        PathMatcher wixInstallDirMatcher = FileSystems.getDefault().getPathMatcher(
+                "glob:WiX Toolset v*");
+
+        Path programFiles = getSystemDir("ProgramFiles", "\\Program Files");
+        Path programFilesX86 = getSystemDir("ProgramFiles(x86)",
+                "\\Program Files (x86)");
+
+        // Returns list of WiX install directories ordered by WiX version number.
+        // Newer versions go first.
+        return Stream.of(programFiles, programFilesX86).map(path -> {
+            List<Path> result;
+            try (var paths = Files.walk(path, 1)) {
+                result = paths.collect(Collectors.toList());
+            } catch (IOException ex) {
+                Log.verbose(ex);
+                result = Collections.emptyList();
+            }
+            return result;
+        }).flatMap(List::stream)
+        .filter(path -> wixInstallDirMatcher.matches(path.getFileName()))
+        .sorted(Comparator.comparing(Path::getFileName).reversed())
+        .map(path -> path.resolve("bin"))
+        .collect(Collectors.toList());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/MsiInstallerStrings_en.wxl	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="1252">
+  <String Id="message.install.dir.exist">The folder [INSTALLDIR] already exist. Would you like to install to that folder anyway?</String>
+  <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>
+</WixLocalization>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/MsiInstallerStrings_ja.wxl	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="932">
+  <String Id="message.install.dir.exist">The folder [INSTALLDIR] already exist. Would you like to install to that folder anyway?</String>
+  <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>
+</WixLocalization>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="936">
+  <String Id="message.install.dir.exist">The folder [INSTALLDIR] already exist. Would you like to install to that folder anyway?</String>
+  <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>
+</WixLocalization>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/WinLauncher.template	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+CompanyName=COMPANY_NAME
+FileDescription=FILE_DESCRIPTION
+FileVersion=FILE_VERSION
+InternalName=INTERNAL_NAME
+LegalCopyright=LEGAL_COPYRIGHT
+OriginalFilename=ORIGINAL_FILENAME
+ProductName=PRODUCT_NAME
+ProductVersion=PRODUCT_VERSION
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/WinResources.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+app.bundler.name=Windows Application Image
+exe.bundler.name=EXE Installer Package
+msi.bundler.name=MSI Installer Package
+
+param.menu-group.default=Unknown
+
+resource.executable-properties-template=Template for creating executable properties file
+resource.setup-icon=setup dialog icon
+resource.post-app-image-script=script to run after application image is populated
+resource.post-msi-script=script to run after msi file for exe installer is created
+resource.wxl-file-name=MsiInstallerStrings_en.wxl
+resource.main-wix-file=Main WiX project file
+resource.overrides-wix-file=Overrides 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.
+error.version-string-wrong-format=Version string is not compatible with MSI rules [{0}]
+error.version-string-wrong-format.advice=Set the bundler argument "{0}" according to these rules: https://msdn.microsoft.com/en-us/library/aa370859%28v\=VS.85%29.aspx .
+error.version-string-major-out-of-range=Major version must be in the range [0, 255]
+error.version-string-build-out-of-range=Build part of version must be in the range [0, 65535]
+error.version-string-minor-out-of-range=Minor version must be in the range [0, 255]
+error.version-string-part-not-number=Failed to convert version component to int
+error.version-swap=Failed to update version information for {0}
+error.invalid-envvar=Invalid value of {0} environment variable
+
+message.result-dir=Result application bundle: {0}.
+message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place.
+message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}".
+message.outputting-to-location=Generating EXE for installer to: {0}.
+message.output-location=Installer (.exe) saved to: {0}
+message.tool-version=Detected [{0}] version [{1}].
+message.creating-association-with-null-extension=Creating association with null extension.
+message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required.
+message.version-string-too-many-components=Version sting may have up to 3 components - major.minor.build .
+message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action.
+message.product-code=MSI ProductCode: {0}.
+message.upgrade-code=MSI UpgradeCode: {0}.
+message.preparing-msi-config=Preparing MSI config: {0}.
+message.generating-msi=Generating MSI: {0}.
+message.invalid.install.dir=Warning: Invalid install directory {0}. Install directory should be a relative sub-path under the default installation location such as "Program Files". Defaulting to application name "{1}".
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/WinResources_ja.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+app.bundler.name=Windows Application Image
+exe.bundler.name=EXE Installer Package
+msi.bundler.name=MSI Installer Package
+
+param.menu-group.default=Unknown
+
+resource.executable-properties-template=Template for creating executable properties file
+resource.setup-icon=setup dialog icon
+resource.post-app-image-script=script to run after application image is populated
+resource.post-msi-script=script to run after msi file for exe installer is created
+resource.wxl-file-name=MsiInstallerStrings_en.wxl
+resource.main-wix-file=Main WiX project file
+resource.overrides-wix-file=Overrides 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.
+error.version-string-wrong-format=Version string is not compatible with MSI rules [{0}]
+error.version-string-wrong-format.advice=Set the bundler argument "{0}" according to these rules: https://msdn.microsoft.com/en-us/library/aa370859%28v\=VS.85%29.aspx .
+error.version-string-major-out-of-range=Major version must be in the range [0, 255]
+error.version-string-build-out-of-range=Build part of version must be in the range [0, 65535]
+error.version-string-minor-out-of-range=Minor version must be in the range [0, 255]
+error.version-string-part-not-number=Failed to convert version component to int
+error.version-swap=Failed to update version information for {0}
+error.invalid-envvar=Invalid value of {0} environment variable
+
+message.result-dir=Result application bundle: {0}.
+message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place.
+message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}".
+message.outputting-to-location=Generating EXE for installer to: {0}.
+message.output-location=Installer (.exe) saved to: {0}
+message.tool-version=Detected [{0}] version [{1}].
+message.creating-association-with-null-extension=Creating association with null extension.
+message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required.
+message.version-string-too-many-components=Version sting may have up to 3 components - major.minor.build .
+message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action.
+message.product-code=MSI ProductCode: {0}.
+message.upgrade-code=MSI UpgradeCode: {0}.
+message.preparing-msi-config=Preparing MSI config: {0}.
+message.generating-msi=Generating MSI: {0}.
+message.invalid.install.dir=Warning: Invalid install directory {0}. Install directory should be a relative sub-path under the default installation location such as "Program Files". Defaulting to application name "{1}".
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/WinResources_zh_CN.properties	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2017, 2019, 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.
+#
+#
+
+app.bundler.name=Windows Application Image
+exe.bundler.name=EXE Installer Package
+msi.bundler.name=MSI Installer Package
+
+param.menu-group.default=Unknown
+
+resource.executable-properties-template=Template for creating executable properties file
+resource.setup-icon=setup dialog icon
+resource.post-app-image-script=script to run after application image is populated
+resource.post-msi-script=script to run after msi file for exe installer is created
+resource.wxl-file-name=MsiInstallerStrings_en.wxl
+resource.main-wix-file=Main WiX project file
+resource.overrides-wix-file=Overrides 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.
+error.version-string-wrong-format=Version string is not compatible with MSI rules [{0}]
+error.version-string-wrong-format.advice=Set the bundler argument "{0}" according to these rules: https://msdn.microsoft.com/en-us/library/aa370859%28v\=VS.85%29.aspx .
+error.version-string-major-out-of-range=Major version must be in the range [0, 255]
+error.version-string-build-out-of-range=Build part of version must be in the range [0, 65535]
+error.version-string-minor-out-of-range=Minor version must be in the range [0, 255]
+error.version-string-part-not-number=Failed to convert version component to int
+error.version-swap=Failed to update version information for {0}
+error.invalid-envvar=Invalid value of {0} environment variable
+
+message.result-dir=Result application bundle: {0}.
+message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place.
+message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}".
+message.outputting-to-location=Generating EXE for installer to: {0}.
+message.output-location=Installer (.exe) saved to: {0}
+message.tool-version=Detected [{0}] version [{1}].
+message.creating-association-with-null-extension=Creating association with null extension.
+message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required.
+message.version-string-too-many-components=Version sting may have up to 3 components - major.minor.build .
+message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action.
+message.product-code=MSI ProductCode: {0}.
+message.upgrade-code=MSI UpgradeCode: {0}.
+message.preparing-msi-config=Preparing MSI config: {0}.
+message.generating-msi=Generating MSI: {0}.
+message.invalid.install.dir=Warning: Invalid install directory {0}. Install directory should be a relative sub-path under the default installation location such as "Program Files". Defaulting to application name "{1}".
+
Binary file src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/java48.ico has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/main.wxs	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
+     xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
+
+  <?ifdef JpIsSystemWide ?>
+    <?define JpInstallScope="perMachine"?>
+  <?else?>
+    <?define JpInstallScope="perUser"?>
+  <?endif?>
+
+  <?define JpProductLanguage=1033 ?>
+  <?define JpInstallerVersion=200 ?>
+  <?define JpCompressedMsi=yes ?>
+
+  <?include $(var.JpConfigDir)/overrides.wxi ?>
+
+  <Product
+    Id="$(var.JpProductCode)"
+    Name="$(var.JpAppName)"
+    Language="$(var.JpProductLanguage)"
+    Version="$(var.JpAppVersion)"
+    Manufacturer="$(var.JpAppVendor)"
+    UpgradeCode="$(var.JpProductUpgradeCode)">
+
+    <Package
+      Description="$(var.JpAppDescription)"
+      Manufacturer="$(var.JpAppVendor)"
+      InstallerVersion="$(var.JpInstallerVersion)"
+      Compressed="$(var.JpCompressedMsi)"
+      InstallScope="$(var.JpInstallScope)" Platform="x64"
+    />
+
+    <Media Id="1" Cabinet="Data.cab" EmbedCab="yes" />
+
+    <?ifdef JpAllowDowngrades ?>
+    <?ifdef JpAllowUpgrades ?>
+    <MajorUpgrade
+      AllowDowngrades="yes"
+      Disallow="no"
+    />
+    <?endif?>
+    <?endif?>
+
+    <?ifdef JpAllowDowngrades ?>
+    <?ifndef JpAllowUpgrades ?>
+    <MajorUpgrade
+      AllowDowngrades="yes"
+      Disallow="yes"
+      DisallowUpgradeErrorMessage="!(loc.DisallowUpgradeErrorMessage)"
+    />
+    <?endif?>
+    <?endif?>
+
+    <?ifndef JpAllowDowngrades ?>
+    <?ifdef JpAllowUpgrades ?>
+    <MajorUpgrade
+      AllowDowngrades="no"
+      Disallow="no"
+      DowngradeErrorMessage="!(loc.DowngradeErrorMessage)"
+    />
+    <?endif?>
+    <?endif?>
+
+    <?ifndef JpAllowDowngrades ?>
+    <?ifndef JpAllowUpgrades ?>
+    <MajorUpgrade
+      AllowDowngrades="no"
+      Disallow="yes"
+      DowngradeErrorMessage="!(loc.DowngradeErrorMessage)"
+      DisallowUpgradeErrorMessage="!(loc.DisallowUpgradeErrorMessage)"
+    />
+    <?endif?>
+    <?endif?>
+
+    <!-- Standard required root -->
+    <Directory Id="TARGETDIR" Name="SourceDir"/>
+
+    <Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1">
+      <ComponentGroupRef Id="Shortcuts"/>
+      <ComponentGroupRef Id="Files"/>
+      <ComponentGroupRef Id="FileAssociations"/>
+    </Feature>
+
+    <?ifdef JpInstallDirChooser ?>
+    <Binary Id="JpCaDll" SourceFile="wixhelper.dll"/>
+    <CustomAction Id="JpCheckInstallDir" BinaryKey="JpCaDll" DllEntry="CheckInstallDir" />
+    <?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?>
+
+  </Product>
+</Wix>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/resources/overrides.wxi	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Stub by design -->
+<Include/>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/classes/module-info.java.extra	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+
+provides jdk.incubator.jpackage.internal.Bundler with
+    jdk.incubator.jpackage.internal.WinAppBundler,
+    jdk.incubator.jpackage.internal.WinExeBundler,
+    jdk.incubator.jpackage.internal.WinMsiBundler;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/jpackageapplauncher/WinLauncher.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012, 2019, 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.
+ */
+
+#include <Windows.h>
+#include <Shellapi.h>
+#include <locale.h>
+#include <tchar.h>
+#include <string>
+
+#define JPACKAGE_LIBRARY TEXT("applauncher.dll")
+
+typedef bool (*start_launcher)(int argc, TCHAR* argv[]);
+typedef void (*stop_launcher)();
+
+std::wstring GetTitle() {
+    std::wstring result;
+    wchar_t buffer[MAX_PATH];
+    GetModuleFileName(NULL, buffer, MAX_PATH - 1);
+    buffer[MAX_PATH - 1] = '\0';
+    result = buffer;
+    size_t slash = result.find_last_of('\\');
+
+    if (slash != std::wstring::npos)
+        result = result.substr(slash + 1, result.size() - slash - 1);
+
+    return result;
+}
+
+#ifdef LAUNCHERC
+int main(int argc0, char *argv0[]) {
+#else // LAUNCHERC
+int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+                       LPTSTR lpCmdLine, int nCmdShow) {
+#endif // LAUNCHERC
+    int result = 1;
+    TCHAR **argv;
+    int argc;
+
+    // [RT-31061] otherwise UI can be left in back of other windows.
+    ::AllowSetForegroundWindow(ASFW_ANY);
+
+    ::setlocale(LC_ALL, "en_US.utf8");
+    argv = CommandLineToArgvW(GetCommandLine(), &argc);
+
+    HMODULE library = ::LoadLibrary(JPACKAGE_LIBRARY);
+
+    if (library == NULL) {
+        std::wstring title = GetTitle();
+        std::wstring description = std::wstring(JPACKAGE_LIBRARY)
+                + std::wstring(TEXT(" not found."));
+        MessageBox(NULL, description.data(),
+                title.data(), MB_ICONERROR | MB_OK);
+    }
+    else {
+        start_launcher start =
+                (start_launcher)GetProcAddress(library, "start_launcher");
+        stop_launcher stop =
+                (stop_launcher)GetProcAddress(library, "stop_launcher");
+
+        if (start != NULL && stop != NULL) {
+            if (start(argc, argv) == true) {
+                result = 0;
+                stop();
+            }
+        }
+
+        ::FreeLibrary(library);
+    }
+
+    if (argv != NULL) {
+        LocalFree(argv);
+    }
+
+    return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libapplauncher/DllMain.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <windows.h>
+
+extern "C" {
+
+    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
+            LPVOID lpvReserved) {
+        return true;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libapplauncher/FileAttribute.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef FILEATTRIBUTE_H
+#define FILEATTRIBUTE_H
+
+enum FileAttribute {
+    faArchive = FILE_ATTRIBUTE_ARCHIVE,
+    faCompressed = FILE_ATTRIBUTE_COMPRESSED,
+    faDevice = FILE_ATTRIBUTE_DEVICE,
+    faDirectory = FILE_ATTRIBUTE_DIRECTORY,
+    faEncrypted = FILE_ATTRIBUTE_ENCRYPTED,
+    faHidden = FILE_ATTRIBUTE_HIDDEN,
+    faNormal = FILE_ATTRIBUTE_NORMAL,
+    faNotContentIndexed = FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
+    faOffline = FILE_ATTRIBUTE_OFFLINE,
+    faSystem = FILE_ATTRIBUTE_SYSTEM,
+    faSymbolicLink = FILE_ATTRIBUTE_REPARSE_POINT,
+    faSparceFile = FILE_ATTRIBUTE_SPARSE_FILE,
+    faReadOnly = FILE_ATTRIBUTE_READONLY,
+    faTemporary = FILE_ATTRIBUTE_TEMPORARY,
+    faVirtual = FILE_ATTRIBUTE_VIRTUAL
+};
+
+#endif // FILEATTRIBUTE_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libapplauncher/FilePath.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,468 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "FilePath.h"
+
+#include <algorithm>
+#include <list>
+#include <ShellAPI.h>
+
+bool FilePath::FileExists(const TString FileName) {
+    bool result = false;
+    WIN32_FIND_DATA FindFileData;
+    TString fileName = FixPathForPlatform(FileName);
+    HANDLE handle = FindFirstFile(fileName.data(), &FindFileData);
+
+    if (handle != INVALID_HANDLE_VALUE) {
+        if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
+            result = true;
+        }
+        else {
+            result = true;
+        }
+
+        FindClose(handle);
+    }
+    return result;
+}
+
+bool FilePath::DirectoryExists(const TString DirectoryName) {
+    bool result = false;
+    WIN32_FIND_DATA FindFileData;
+    TString directoryName = FixPathForPlatform(DirectoryName);
+    HANDLE handle = FindFirstFile(directoryName.data(), &FindFileData);
+
+    if (handle != INVALID_HANDLE_VALUE) {
+        if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
+            result = true;
+        }
+
+        FindClose(handle);
+    }
+    return result;
+}
+
+std::string GetLastErrorAsString() {
+    // Get the error message, if any.
+    DWORD errorMessageID = ::GetLastError();
+
+    if (errorMessageID == 0) {
+        return "No error message has been recorded";
+    }
+
+    LPSTR messageBuffer = NULL;
+    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
+            | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+            NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL,
+            SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
+
+    std::string message(messageBuffer, size);
+
+    // Free the buffer.
+    LocalFree(messageBuffer);
+
+    return message;
+}
+
+bool FilePath::DeleteFile(const TString FileName) {
+    bool result = false;
+
+    if (FileExists(FileName) == true) {
+        TString lFileName = FixPathForPlatform(FileName);
+        FileAttributes attributes(lFileName);
+
+        if (attributes.Contains(faReadOnly) == true) {
+            attributes.Remove(faReadOnly);
+        }
+
+        result = ::DeleteFile(lFileName.data()) == TRUE;
+    }
+
+    return result;
+}
+
+bool FilePath::DeleteDirectory(const TString DirectoryName) {
+    bool result = false;
+
+    if (DirectoryExists(DirectoryName) == true) {
+        SHFILEOPSTRUCTW fos = {0};
+        TString directoryName = FixPathForPlatform(DirectoryName);
+        DynamicBuffer<TCHAR> lDirectoryName(directoryName.size() + 2);
+        if (lDirectoryName.GetData() == NULL) {
+            return false;
+        }
+        memcpy(lDirectoryName.GetData(), directoryName.data(),
+                (directoryName.size() + 2) * sizeof(TCHAR));
+        lDirectoryName[directoryName.size() + 1] = NULL;
+        // Double null terminate for SHFileOperation.
+
+        // Delete the folder and everything inside.
+        fos.wFunc = FO_DELETE;
+        fos.pFrom = lDirectoryName.GetData();
+        fos.fFlags = FOF_NO_UI;
+        result = SHFileOperation(&fos) == 0;
+    }
+
+    return result;
+}
+
+TString FilePath::IncludeTrailingSeparator(const TString value) {
+    TString result = value;
+
+    if (value.size() > 0) {
+        TString::iterator i = result.end();
+        i--;
+
+        if (*i != TRAILING_PATHSEPARATOR) {
+            result += TRAILING_PATHSEPARATOR;
+        }
+    }
+
+    return result;
+}
+
+TString FilePath::IncludeTrailingSeparator(const char* value) {
+    TString lvalue = PlatformString(value).toString();
+    return IncludeTrailingSeparator(lvalue);
+}
+
+TString FilePath::IncludeTrailingSeparator(const wchar_t* value) {
+    TString lvalue = PlatformString(value).toString();
+    return IncludeTrailingSeparator(lvalue);
+}
+
+TString FilePath::ExtractFilePath(TString Path) {
+    TString result;
+    size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
+    if (slash != TString::npos)
+        result = Path.substr(0, slash);
+    return result;
+}
+
+TString FilePath::ExtractFileExt(TString Path) {
+    TString result;
+    size_t dot = Path.find_last_of('.');
+
+    if (dot != TString::npos) {
+        result  = Path.substr(dot, Path.size() - dot);
+    }
+
+    return result;
+}
+
+TString FilePath::ExtractFileName(TString Path) {
+    TString result;
+
+    size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
+    if (slash != TString::npos)
+        result = Path.substr(slash + 1, Path.size() - slash - 1);
+
+    return result;
+}
+
+TString FilePath::ChangeFileExt(TString Path, TString Extension) {
+    TString result;
+    size_t dot = Path.find_last_of('.');
+
+    if (dot != TString::npos) {
+        result = Path.substr(0, dot) + Extension;
+    }
+
+    if (result.empty() == true) {
+        result = Path;
+    }
+
+    return result;
+}
+
+TString FilePath::FixPathForPlatform(TString Path) {
+    TString result = Path;
+    std::replace(result.begin(), result.end(),
+            BAD_TRAILING_PATHSEPARATOR, TRAILING_PATHSEPARATOR);
+    // The maximum path that does not require long path prefix. On Windows the
+    // maximum path is 260 minus 1 (NUL) but for directories it is 260 minus
+    // 12 minus 1 (to allow for the creation of a 8.3 file in the directory).
+    const int maxPath = 247;
+    if (result.length() > maxPath &&
+        result.find(_T("\\\\?\\")) == TString::npos &&
+        result.find(_T("\\\\?\\UNC")) == TString::npos) {
+        const TString prefix(_T("\\\\"));
+        if (!result.compare(0, prefix.size(), prefix)) {
+            // UNC path, converting to UNC path in long notation
+            result = _T("\\\\?\\UNC") + result.substr(1, result.length());
+        } else {
+            // converting to non-UNC path in long notation
+            result = _T("\\\\?\\") + result;
+        }
+    }
+    return result;
+}
+
+TString FilePath::FixPathSeparatorForPlatform(TString Path) {
+    TString result = Path;
+    std::replace(result.begin(), result.end(),
+            BAD_PATH_SEPARATOR, PATH_SEPARATOR);
+    return result;
+}
+
+TString FilePath::PathSeparator() {
+    TString result;
+    result = PATH_SEPARATOR;
+    return result;
+}
+
+bool FilePath::CreateDirectory(TString Path, bool ownerOnly) {
+    bool result = false;
+
+    std::list<TString> paths;
+    TString lpath = Path;
+
+    while (lpath.empty() == false && DirectoryExists(lpath) == false) {
+        paths.push_front(lpath);
+        lpath = ExtractFilePath(lpath);
+    }
+
+    for (std::list<TString>::iterator iterator = paths.begin();
+            iterator != paths.end(); iterator++) {
+        lpath = *iterator;
+
+        if (_wmkdir(lpath.data()) == 0) {
+            result = true;
+        } else {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+void FilePath::ChangePermissions(TString FileName, bool ownerOnly) {
+}
+
+#include <algorithm>
+
+FileAttributes::FileAttributes(const TString FileName, bool FollowLink) {
+    FFileName = FileName;
+    FFollowLink = FollowLink;
+    ReadAttributes();
+}
+
+bool FileAttributes::WriteAttributes() {
+    bool result = false;
+
+    DWORD attributes = 0;
+
+    for (std::vector<FileAttribute>::const_iterator iterator =
+            FAttributes.begin();
+        iterator != FAttributes.end(); iterator++) {
+        switch (*iterator) {
+            case faArchive: {
+                attributes = attributes & FILE_ATTRIBUTE_ARCHIVE;
+                break;
+            }
+            case faCompressed: {
+                attributes = attributes & FILE_ATTRIBUTE_COMPRESSED;
+                break;
+            }
+            case faDevice: {
+                attributes = attributes & FILE_ATTRIBUTE_DEVICE;
+                break;
+            }
+            case faDirectory: {
+                attributes = attributes & FILE_ATTRIBUTE_DIRECTORY;
+                break;
+            }
+            case faEncrypted: {
+                attributes = attributes & FILE_ATTRIBUTE_ENCRYPTED;
+                break;
+            }
+            case faHidden: {
+                attributes = attributes & FILE_ATTRIBUTE_HIDDEN;
+                break;
+            }
+            case faNormal: {
+                attributes = attributes & FILE_ATTRIBUTE_NORMAL;
+                break;
+            }
+            case faNotContentIndexed: {
+                attributes = attributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+                break;
+            }
+            case faOffline: {
+                attributes = attributes & FILE_ATTRIBUTE_OFFLINE;
+                break;
+            }
+            case faSystem: {
+                attributes = attributes & FILE_ATTRIBUTE_SYSTEM;
+                break;
+            }
+            case faSymbolicLink: {
+                attributes = attributes & FILE_ATTRIBUTE_REPARSE_POINT;
+                break;
+            }
+            case faSparceFile: {
+                attributes = attributes & FILE_ATTRIBUTE_SPARSE_FILE;
+                break;
+            }
+            case faReadOnly: {
+                attributes = attributes & FILE_ATTRIBUTE_READONLY;
+                break;
+            }
+            case faTemporary: {
+                attributes = attributes & FILE_ATTRIBUTE_TEMPORARY;
+                break;
+            }
+            case faVirtual: {
+                attributes = attributes & FILE_ATTRIBUTE_VIRTUAL;
+                break;
+            }
+        }
+    }
+
+    if (::SetFileAttributes(FFileName.data(), attributes) != 0) {
+        result = true;
+    }
+
+    return result;
+}
+
+#define S_ISRUSR(m)    (((m) & S_IRWXU) == S_IRUSR)
+#define S_ISWUSR(m)    (((m) & S_IRWXU) == S_IWUSR)
+#define S_ISXUSR(m)    (((m) & S_IRWXU) == S_IXUSR)
+
+#define S_ISRGRP(m)    (((m) & S_IRWXG) == S_IRGRP)
+#define S_ISWGRP(m)    (((m) & S_IRWXG) == S_IWGRP)
+#define S_ISXGRP(m)    (((m) & S_IRWXG) == S_IXGRP)
+
+#define S_ISROTH(m)    (((m) & S_IRWXO) == S_IROTH)
+#define S_ISWOTH(m)    (((m) & S_IRWXO) == S_IWOTH)
+#define S_ISXOTH(m)    (((m) & S_IRWXO) == S_IXOTH)
+
+bool FileAttributes::ReadAttributes() {
+    bool result = false;
+
+    DWORD attributes = ::GetFileAttributes(FFileName.data());
+
+    if (attributes != INVALID_FILE_ATTRIBUTES) {
+        result = true;
+
+        if (attributes | FILE_ATTRIBUTE_ARCHIVE) {
+            FAttributes.push_back(faArchive);
+        }
+        if (attributes | FILE_ATTRIBUTE_COMPRESSED) {
+            FAttributes.push_back(faCompressed);
+        }
+        if (attributes | FILE_ATTRIBUTE_DEVICE) {
+            FAttributes.push_back(faDevice);
+        }
+        if (attributes | FILE_ATTRIBUTE_DIRECTORY) {
+            FAttributes.push_back(faDirectory);
+        }
+        if (attributes | FILE_ATTRIBUTE_ENCRYPTED) {
+            FAttributes.push_back(faEncrypted);
+        }
+        if (attributes | FILE_ATTRIBUTE_HIDDEN) {
+            FAttributes.push_back(faHidden);
+        }
+        if (attributes | FILE_ATTRIBUTE_NORMAL) {
+            FAttributes.push_back(faNormal);
+        }
+        if (attributes | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) {
+            FAttributes.push_back(faNotContentIndexed);
+        }
+        if (attributes | FILE_ATTRIBUTE_SYSTEM) {
+            FAttributes.push_back(faSystem);
+        }
+        if (attributes | FILE_ATTRIBUTE_OFFLINE) {
+            FAttributes.push_back(faOffline);
+        }
+        if (attributes | FILE_ATTRIBUTE_REPARSE_POINT) {
+            FAttributes.push_back(faSymbolicLink);
+        }
+        if (attributes | FILE_ATTRIBUTE_SPARSE_FILE) {
+            FAttributes.push_back(faSparceFile);
+        }
+        if (attributes | FILE_ATTRIBUTE_READONLY ) {
+            FAttributes.push_back(faReadOnly);
+        }
+        if (attributes | FILE_ATTRIBUTE_TEMPORARY) {
+            FAttributes.push_back(faTemporary);
+        }
+        if (attributes | FILE_ATTRIBUTE_VIRTUAL) {
+            FAttributes.push_back(faVirtual);
+        }
+    }
+
+    return result;
+}
+
+bool FileAttributes::Valid(const FileAttribute Value) {
+    bool result = false;
+
+    switch (Value) {
+        case faHidden:
+        case faReadOnly: {
+            result = true;
+            break;
+        }
+        default:
+            break;
+    }
+
+    return result;
+}
+
+void FileAttributes::Append(FileAttribute Value) {
+    if (Valid(Value) == true) {
+        FAttributes.push_back(Value);
+        WriteAttributes();
+    }
+}
+
+bool FileAttributes::Contains(FileAttribute Value) {
+    bool result = false;
+
+    std::vector<FileAttribute>::const_iterator iterator =
+            std::find(FAttributes.begin(), FAttributes.end(), Value);
+
+    if (iterator != FAttributes.end()) {
+        result = true;
+    }
+
+    return result;
+}
+
+void FileAttributes::Remove(FileAttribute Value) {
+    if (Valid(Value) == true) {
+        std::vector<FileAttribute>::iterator iterator =
+            std::find(FAttributes.begin(), FAttributes.end(), Value);
+
+        if (iterator != FAttributes.end()) {
+            FAttributes.erase(iterator);
+            WriteAttributes();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libapplauncher/PlatformDefs.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef PLATFORM_DEFS_H
+#define PLATFORM_DEFS_H
+
+// Define Windows compatibility requirements XP or later
+#define WINVER 0x0600
+#define _WIN32_WINNT 0x0600
+
+#include <Windows.h>
+#include <tchar.h>
+#include <shlobj.h>
+#include <direct.h>
+#include <process.h>
+#include <malloc.h>
+#include <string>
+
+using namespace std;
+
+#ifndef WINDOWS
+#define WINDOWS
+#endif
+
+typedef std::wstring TString;
+#define StringLength wcslen
+
+#define TRAILING_PATHSEPARATOR '\\'
+#define BAD_TRAILING_PATHSEPARATOR '/'
+#define PATH_SEPARATOR ';'
+#define BAD_PATH_SEPARATOR ':'
+
+typedef ULONGLONG TPlatformNumber;
+typedef DWORD TProcessID;
+
+typedef void* Module;
+typedef void* Procedure;
+
+#endif // PLATFORM_DEFS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libapplauncher/WindowsPlatform.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,759 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#include "Platform.h"
+
+#include "JavaVirtualMachine.h"
+#include "WindowsPlatform.h"
+#include "Package.h"
+#include "Helpers.h"
+#include "PlatformString.h"
+#include "Macros.h"
+
+#include <map>
+#include <vector>
+#include <regex>
+#include <fstream>
+#include <locale>
+#include <codecvt>
+
+using namespace std;
+
+#define WINDOWS_JPACKAGE_TMP_DIR \
+        L"\\AppData\\Local\\Java\\JPackage\\tmp"
+
+class Registry {
+private:
+    HKEY FKey;
+    HKEY FOpenKey;
+    bool FOpen;
+
+public:
+
+    Registry(HKEY Key) {
+        FOpen = false;
+        FKey = Key;
+    }
+
+    ~Registry() {
+        Close();
+    }
+
+    void Close() {
+        if (FOpen == true) {
+            RegCloseKey(FOpenKey);
+        }
+    }
+
+    bool Open(TString SubKey) {
+        bool result = false;
+        Close();
+
+        if (RegOpenKeyEx(FKey, SubKey.data(), 0, KEY_READ, &FOpenKey) ==
+                ERROR_SUCCESS) {
+            result = true;
+        }
+
+        return result;
+    }
+
+    std::list<TString> GetKeys() {
+        std::list<TString> result;
+        DWORD count;
+
+        if (RegQueryInfoKey(FOpenKey, NULL, NULL, NULL, NULL, NULL, NULL,
+                &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
+
+            DWORD length = 255;
+            DynamicBuffer<TCHAR> buffer(length);
+            if (buffer.GetData() == NULL) {
+                return result;
+            }
+
+            for (unsigned int index = 0; index < count; index++) {
+                buffer.Zero();
+                DWORD status = RegEnumValue(FOpenKey, index, buffer.GetData(),
+                        &length, NULL, NULL, NULL, NULL);
+
+                while (status == ERROR_MORE_DATA) {
+                    length = length * 2;
+                    if (!buffer.Resize(length)) {
+                        return result;
+                    }
+                    status = RegEnumValue(FOpenKey, index, buffer.GetData(),
+                            &length, NULL, NULL, NULL, NULL);
+                }
+
+                if (status == ERROR_SUCCESS) {
+                    TString value = buffer.GetData();
+                    result.push_back(value);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    TString ReadString(TString Name) {
+        TString result;
+        DWORD length;
+        DWORD dwRet;
+        DynamicBuffer<wchar_t> buffer(0);
+        length = 0;
+
+        dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, NULL,
+                &length);
+        if (dwRet == ERROR_MORE_DATA || dwRet == 0) {
+            if (!buffer.Resize(length + 1)) {
+                return result;
+            }
+            dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL,
+                    (LPBYTE) buffer.GetData(), &length);
+            result = buffer.GetData();
+        }
+
+        return result;
+    }
+};
+
+WindowsPlatform::WindowsPlatform(void) : Platform() {
+    FMainThread = ::GetCurrentThreadId();
+}
+
+WindowsPlatform::~WindowsPlatform(void) {
+}
+
+TString WindowsPlatform::GetPackageAppDirectory() {
+    return FilePath::IncludeTrailingSeparator(
+            GetPackageRootDirectory()) + _T("app");
+}
+
+TString WindowsPlatform::GetPackageLauncherDirectory() {
+    return  GetPackageRootDirectory();
+}
+
+TString WindowsPlatform::GetPackageRuntimeBinDirectory() {
+    return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory()) + _T("runtime\\bin");
+}
+
+TCHAR* WindowsPlatform::ConvertStringToFileSystemString(TCHAR* Source,
+        bool &release) {
+    // Not Implemented.
+    return NULL;
+}
+
+TCHAR* WindowsPlatform::ConvertFileSystemStringToString(TCHAR* Source,
+        bool &release) {
+    // Not Implemented.
+    return NULL;
+}
+
+TString WindowsPlatform::GetPackageRootDirectory() {
+    TString result;
+    TString filename = GetModuleFileName();
+    return FilePath::ExtractFilePath(filename);
+}
+
+TString WindowsPlatform::GetAppDataDirectory() {
+    TString result;
+    TCHAR path[MAX_PATH];
+
+    if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path) == S_OK) {
+        result = path;
+    }
+
+    return result;
+}
+
+TString WindowsPlatform::GetAppName() {
+    TString result = GetModuleFileName();
+    result = FilePath::ExtractFileName(result);
+    result = FilePath::ChangeFileExt(result, _T(""));
+    return result;
+}
+
+void WindowsPlatform::ShowMessage(TString title, TString description) {
+    MessageBox(NULL, description.data(),
+            !title.empty() ? title.data() : description.data(),
+            MB_ICONERROR | MB_OK);
+}
+
+void WindowsPlatform::ShowMessage(TString description) {
+    TString appname = GetModuleFileName();
+    appname = FilePath::ExtractFileName(appname);
+    MessageBox(NULL, description.data(), appname.data(), MB_ICONERROR | MB_OK);
+}
+
+MessageResponse WindowsPlatform::ShowResponseMessage(TString title,
+        TString description) {
+    MessageResponse result = mrCancel;
+
+    if (::MessageBox(NULL, description.data(), title.data(), MB_OKCANCEL) ==
+            IDOK) {
+        result = mrOK;
+    }
+
+    return result;
+}
+
+TString WindowsPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) {
+    TString result = FilePath::IncludeTrailingSeparator(RuntimePath) +
+            _T("jre\\bin\\jli.dll");
+
+    if (FilePath::FileExists(result) == false) {
+        result = FilePath::IncludeTrailingSeparator(RuntimePath) +
+                _T("bin\\jli.dll");
+    }
+
+    return result;
+}
+
+ISectionalPropertyContainer* WindowsPlatform::GetConfigFile(TString FileName) {
+    IniFile *result = new IniFile();
+    if (result == NULL) {
+        return NULL;
+    }
+
+    result->LoadFromFile(FileName);
+
+    return result;
+}
+
+TString WindowsPlatform::GetModuleFileName() {
+    TString result;
+    DynamicBuffer<wchar_t> buffer(MAX_PATH);
+    if (buffer.GetData() == NULL) {
+        return result;
+    }
+
+    ::GetModuleFileName(NULL, buffer.GetData(),
+            static_cast<DWORD> (buffer.GetSize()));
+
+    while (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
+        if (!buffer.Resize(buffer.GetSize() * 2)) {
+            return result;
+        }
+        ::GetModuleFileName(NULL, buffer.GetData(),
+                static_cast<DWORD> (buffer.GetSize()));
+    }
+
+    result = buffer.GetData();
+    return result;
+}
+
+Module WindowsPlatform::LoadLibrary(TString FileName) {
+    return ::LoadLibrary(FileName.data());
+}
+
+void WindowsPlatform::FreeLibrary(Module AModule) {
+    ::FreeLibrary((HMODULE) AModule);
+}
+
+Procedure WindowsPlatform::GetProcAddress(Module AModule,
+        std::string MethodName) {
+    return ::GetProcAddress((HMODULE) AModule, MethodName.c_str());
+}
+
+bool WindowsPlatform::IsMainThread() {
+    bool result = (FMainThread == ::GetCurrentThreadId());
+    return result;
+}
+
+TString WindowsPlatform::GetTempDirectory() {
+    TString result;
+    PWSTR userDir = 0;
+
+    if (SUCCEEDED(SHGetKnownFolderPath(
+            FOLDERID_Profile,
+            0,
+            NULL,
+            &userDir))) {
+        result = userDir;
+        result += WINDOWS_JPACKAGE_TMP_DIR;
+        CoTaskMemFree(userDir);
+    }
+
+    return result;
+}
+
+static BOOL CALLBACK enumWindows(HWND winHandle, LPARAM lParam) {
+    DWORD pid = (DWORD) lParam, wPid = 0;
+    GetWindowThreadProcessId(winHandle, &wPid);
+    if (pid == wPid) {
+        SetForegroundWindow(winHandle);
+        return FALSE;
+    }
+    return TRUE;
+}
+
+TPlatformNumber WindowsPlatform::GetMemorySize() {
+    SYSTEM_INFO si;
+    GetSystemInfo(&si);
+    size_t result = (size_t) si.lpMaximumApplicationAddress;
+    result = result / 1048576; // Convert from bytes to megabytes.
+    return result;
+}
+
+std::vector<TString> FilterList(std::vector<TString> &Items,
+        std::wregex Pattern) {
+    std::vector<TString> result;
+
+    for (std::vector<TString>::iterator it = Items.begin();
+            it != Items.end(); ++it) {
+        TString item = *it;
+        std::wsmatch match;
+
+        if (std::regex_search(item, match, Pattern)) {
+            result.push_back(item);
+        }
+    }
+    return result;
+}
+
+Process* WindowsPlatform::CreateProcess() {
+    return new WindowsProcess();
+}
+
+void WindowsPlatform::InitStreamLocale(wios *stream) {
+    const std::locale empty_locale = std::locale::empty();
+    const std::locale utf8_locale =
+                std::locale(empty_locale, new std::codecvt_utf8<wchar_t>());
+    stream->imbue(utf8_locale);
+}
+
+void WindowsPlatform::addPlatformDependencies(JavaLibrary *pJavaLibrary) {
+    if (pJavaLibrary == NULL) {
+        return;
+    }
+
+    if (FilePath::FileExists(_T("msvcr100.dll")) == true) {
+        pJavaLibrary->AddDependency(_T("msvcr100.dll"));
+    }
+
+    TString runtimeBin = GetPackageRuntimeBinDirectory();
+    SetDllDirectory(runtimeBin.c_str());
+}
+
+void Platform::CopyString(char *Destination,
+        size_t NumberOfElements, const char *Source) {
+    strcpy_s(Destination, NumberOfElements, Source);
+
+    if (NumberOfElements > 0) {
+        Destination[NumberOfElements - 1] = '\0';
+    }
+}
+
+void Platform::CopyString(wchar_t *Destination,
+        size_t NumberOfElements, const wchar_t *Source) {
+    wcscpy_s(Destination, NumberOfElements, Source);
+
+    if (NumberOfElements > 0) {
+        Destination[NumberOfElements - 1] = '\0';
+    }
+}
+
+// Owner must free the return value.
+MultibyteString Platform::WideStringToMultibyteString(
+        const wchar_t* value) {
+    MultibyteString result;
+    size_t count = 0;
+
+    if (value == NULL) {
+        return result;
+    }
+
+    count = WideCharToMultiByte(CP_UTF8, 0, value, -1, NULL, 0, NULL, NULL);
+
+    if (count > 0) {
+        result.data = new char[count + 1];
+        result.length = WideCharToMultiByte(CP_UTF8, 0, value, -1,
+                result.data, (int)count, NULL, NULL);
+    }
+
+    return result;
+}
+
+// Owner must free the return value.
+WideString Platform::MultibyteStringToWideString(const char* value) {
+    WideString result;
+    size_t count = 0;
+
+    if (value == NULL) {
+        return result;
+    }
+
+    mbstowcs_s(&count, NULL, 0, value, _TRUNCATE);
+
+    if (count > 0) {
+        result.data = new wchar_t[count + 1];
+        mbstowcs_s(&result.length, result.data, count, value, count);
+    }
+
+    return result;
+}
+
+FileHandle::FileHandle(std::wstring FileName) {
+    FHandle = ::CreateFile(FileName.data(), GENERIC_READ, FILE_SHARE_READ,
+            NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+}
+
+FileHandle::~FileHandle() {
+    if (IsValid() == true) {
+        ::CloseHandle(FHandle);
+    }
+}
+
+bool FileHandle::IsValid() {
+    return FHandle != INVALID_HANDLE_VALUE;
+}
+
+HANDLE FileHandle::GetHandle() {
+    return FHandle;
+}
+
+FileMappingHandle::FileMappingHandle(HANDLE FileHandle) {
+    FHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
+}
+
+bool FileMappingHandle::IsValid() {
+    return FHandle != NULL;
+}
+
+FileMappingHandle::~FileMappingHandle() {
+    if (IsValid() == true) {
+        ::CloseHandle(FHandle);
+    }
+}
+
+HANDLE FileMappingHandle::GetHandle() {
+    return FHandle;
+}
+
+FileData::FileData(HANDLE Handle) {
+    FBaseAddress = ::MapViewOfFile(Handle, FILE_MAP_READ, 0, 0, 0);
+}
+
+FileData::~FileData() {
+    if (IsValid() == true) {
+        ::UnmapViewOfFile(FBaseAddress);
+    }
+}
+
+bool FileData::IsValid() {
+    return FBaseAddress != NULL;
+}
+
+LPVOID FileData::GetBaseAddress() {
+    return FBaseAddress;
+}
+
+WindowsLibrary::WindowsLibrary(std::wstring FileName) {
+    FFileName = FileName;
+}
+
+std::vector<TString> WindowsLibrary::GetImports() {
+    std::vector<TString> result;
+    FileHandle library(FFileName);
+
+    if (library.IsValid() == true) {
+        FileMappingHandle mapping(library.GetHandle());
+
+        if (mapping.IsValid() == true) {
+            FileData fileData(mapping.GetHandle());
+
+            if (fileData.IsValid() == true) {
+                PIMAGE_DOS_HEADER dosHeader =
+                        (PIMAGE_DOS_HEADER) fileData.GetBaseAddress();
+                PIMAGE_FILE_HEADER pImgFileHdr =
+                        (PIMAGE_FILE_HEADER) fileData.GetBaseAddress();
+                if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
+                    result = DumpPEFile(dosHeader);
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+// Given an RVA, look up the section header that encloses it and return a
+// pointer to its IMAGE_SECTION_HEADER
+
+PIMAGE_SECTION_HEADER WindowsLibrary::GetEnclosingSectionHeader(DWORD rva,
+        PIMAGE_NT_HEADERS pNTHeader) {
+    PIMAGE_SECTION_HEADER result = 0;
+    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
+
+    for (unsigned index = 0; index < pNTHeader->FileHeader.NumberOfSections;
+            index++, section++) {
+        // Is the RVA is within this section?
+        if ((rva >= section->VirtualAddress) &&
+                (rva < (section->VirtualAddress + section->Misc.VirtualSize))) {
+            result = section;
+        }
+    }
+
+    return result;
+}
+
+LPVOID WindowsLibrary::GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader,
+        DWORD imageBase) {
+    LPVOID result = 0;
+    PIMAGE_SECTION_HEADER pSectionHdr = GetEnclosingSectionHeader(rva,
+            pNTHeader);
+
+    if (pSectionHdr != NULL) {
+        INT delta = (INT) (
+                pSectionHdr->VirtualAddress - pSectionHdr->PointerToRawData);
+        DWORD_PTR dwp = (DWORD_PTR) (imageBase + rva - delta);
+        result = reinterpret_cast<LPVOID> (dwp); // VS2017 - FIXME
+    }
+
+    return result;
+}
+
+std::vector<TString> WindowsLibrary::GetImportsSection(DWORD base,
+        PIMAGE_NT_HEADERS pNTHeader) {
+    std::vector<TString> result;
+
+    // Look up where the imports section is located. Normally in
+    // the .idata section,
+    // but not necessarily so. Therefore, grab the RVA from the data dir.
+    DWORD importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[
+            IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
+
+    if (importsStartRVA != NULL) {
+        // Get the IMAGE_SECTION_HEADER that contains the imports. This is
+        // usually the .idata section, but doesn't have to be.
+        PIMAGE_SECTION_HEADER pSection =
+                GetEnclosingSectionHeader(importsStartRVA, pNTHeader);
+
+        if (pSection != NULL) {
+            PIMAGE_IMPORT_DESCRIPTOR importDesc =
+                    (PIMAGE_IMPORT_DESCRIPTOR) GetPtrFromRVA(
+                    importsStartRVA, pNTHeader, base);
+
+            if (importDesc != NULL) {
+                while (true) {
+                    // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR
+                    if ((importDesc->TimeDateStamp == 0) &&
+                            (importDesc->Name == 0)) {
+                        break;
+                    }
+
+                    std::string filename = (char*) GetPtrFromRVA(
+                            importDesc->Name, pNTHeader, base);
+                    result.push_back(PlatformString(filename));
+                    importDesc++; // advance to next IMAGE_IMPORT_DESCRIPTOR
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+std::vector<TString> WindowsLibrary::DumpPEFile(PIMAGE_DOS_HEADER dosHeader) {
+    std::vector<TString> result;
+    // all of this is VS2017 - FIXME
+    DWORD_PTR dwDosHeaders = reinterpret_cast<DWORD_PTR> (dosHeader);
+    DWORD_PTR dwPIHeaders = dwDosHeaders + (DWORD) (dosHeader->e_lfanew);
+
+    PIMAGE_NT_HEADERS pNTHeader =
+            reinterpret_cast<PIMAGE_NT_HEADERS> (dwPIHeaders);
+
+    // Verify that the e_lfanew field gave us a reasonable
+    // pointer and the PE signature.
+    // TODO: To really fix JDK-8131321 this condition needs to be changed.
+    // There is a matching change
+    // in JavaVirtualMachine.cpp that also needs to be changed.
+    if (pNTHeader->Signature == IMAGE_NT_SIGNATURE) {
+        DWORD base = (DWORD) (dwDosHeaders);
+        result = GetImportsSection(base, pNTHeader);
+    }
+
+    return result;
+}
+
+#include <TlHelp32.h>
+
+WindowsJob::WindowsJob() {
+    FHandle = NULL;
+}
+
+WindowsJob::~WindowsJob() {
+    if (FHandle != NULL) {
+        CloseHandle(FHandle);
+    }
+}
+
+HANDLE WindowsJob::GetHandle() {
+    if (FHandle == NULL) {
+        FHandle = CreateJobObject(NULL, NULL); // GLOBAL
+
+        if (FHandle == NULL) {
+            ::MessageBox(0, _T("Could not create job object"),
+                    _T("TEST"), MB_OK);
+        } else {
+            JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
+
+            // Configure all child processes associated with
+            // the job to terminate when the
+            jeli.BasicLimitInformation.LimitFlags =
+                    JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+            if (0 == SetInformationJobObject(FHandle,
+                    JobObjectExtendedLimitInformation, &jeli, sizeof (jeli))) {
+                ::MessageBox(0, _T("Could not SetInformationJobObject"),
+                        _T("TEST"), MB_OK);
+            }
+        }
+    }
+
+    return FHandle;
+}
+
+// Initialize static member of WindowsProcess
+WindowsJob WindowsProcess::FJob;
+
+WindowsProcess::WindowsProcess() : Process() {
+    FRunning = false;
+}
+
+WindowsProcess::~WindowsProcess() {
+    Terminate();
+}
+
+void WindowsProcess::Cleanup() {
+    CloseHandle(FProcessInfo.hProcess);
+    CloseHandle(FProcessInfo.hThread);
+}
+
+bool WindowsProcess::IsRunning() {
+    bool result = false;
+
+    HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
+    if (handle == INVALID_HANDLE_VALUE) {
+        return false;
+    }
+
+    PROCESSENTRY32 process = {0};
+    process.dwSize = sizeof (process);
+
+    if (::Process32First(handle, &process)) {
+        do {
+            if (process.th32ProcessID == FProcessInfo.dwProcessId) {
+                result = true;
+                break;
+            }
+        } while (::Process32Next(handle, &process));
+    }
+
+    CloseHandle(handle);
+
+    return result;
+}
+
+bool WindowsProcess::Terminate() {
+    bool result = false;
+
+    if (IsRunning() == true && FRunning == true) {
+        FRunning = false;
+    }
+
+    return result;
+}
+
+bool WindowsProcess::Execute(const TString Application,
+        const std::vector<TString> Arguments, bool AWait) {
+    bool result = false;
+
+    if (FRunning == false) {
+        FRunning = true;
+
+        STARTUPINFO startupInfo;
+        ZeroMemory(&startupInfo, sizeof (startupInfo));
+        startupInfo.cb = sizeof (startupInfo);
+        ZeroMemory(&FProcessInfo, sizeof (FProcessInfo));
+
+        TString command = Application;
+
+        for (std::vector<TString>::const_iterator iterator = Arguments.begin();
+                iterator != Arguments.end(); iterator++) {
+            command += TString(_T(" ")) + *iterator;
+        }
+
+        if (::CreateProcess(Application.data(), (wchar_t*)command.data(), NULL,
+                NULL, FALSE, 0, NULL, NULL, &startupInfo, &FProcessInfo)
+                == FALSE) {
+            TString message = PlatformString::Format(
+                    _T("Error: Unable to create process %s"),
+                    Application.data());
+            throw Exception(message);
+        } else {
+            if (FJob.GetHandle() != NULL) {
+                if (::AssignProcessToJobObject(FJob.GetHandle(),
+                        FProcessInfo.hProcess) == 0) {
+                    // Failed to assign process to job. It doesn't prevent
+                    // anything from continuing so continue.
+                }
+            }
+
+            // Wait until child process exits.
+            if (AWait == true) {
+                Wait();
+                // Close process and thread handles.
+                Cleanup();
+            }
+        }
+    }
+
+    return result;
+}
+
+bool WindowsProcess::Wait() {
+    bool result = false;
+
+    WaitForSingleObject(FProcessInfo.hProcess, INFINITE);
+    return result;
+}
+
+TProcessID WindowsProcess::GetProcessID() {
+    return FProcessInfo.dwProcessId;
+}
+
+bool WindowsProcess::ReadOutput() {
+    bool result = false;
+    // TODO implement
+    return result;
+}
+
+void WindowsProcess::SetInput(TString Value) {
+    // TODO implement
+}
+
+std::list<TString> WindowsProcess::GetOutput() {
+    ReadOutput();
+    return Process::GetOutput();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libapplauncher/WindowsPlatform.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+#ifndef WINDOWSPLATFORM_H
+#define WINDOWSPLATFORM_H
+
+#include <Windows.h>
+#include "Platform.h"
+
+class WindowsPlatform : virtual public Platform {
+private:
+    DWORD FMainThread;
+
+public:
+    WindowsPlatform(void);
+    virtual ~WindowsPlatform(void);
+
+    virtual TCHAR* ConvertStringToFileSystemString(TCHAR* Source,
+            bool &release);
+    virtual TCHAR* ConvertFileSystemStringToString(TCHAR* Source,
+            bool &release);
+
+    virtual void ShowMessage(TString title, TString description);
+    virtual void ShowMessage(TString description);
+    virtual MessageResponse ShowResponseMessage(TString title,
+            TString description);
+
+    virtual TString GetPackageRootDirectory();
+    virtual TString GetAppDataDirectory();
+    virtual TString GetAppName();
+    virtual TString GetBundledJavaLibraryFileName(TString RuntimePath);
+    TString GetPackageAppDirectory();
+    TString GetPackageLauncherDirectory();
+    TString GetPackageRuntimeBinDirectory();
+
+    virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
+
+    virtual TString GetModuleFileName();
+    virtual Module LoadLibrary(TString FileName);
+    virtual void FreeLibrary(Module AModule);
+    virtual Procedure GetProcAddress(Module AModule, std::string MethodName);
+
+    virtual Process* CreateProcess();
+
+    virtual bool IsMainThread();
+    virtual TPlatformNumber GetMemorySize();
+
+    virtual TString GetTempDirectory();
+    void InitStreamLocale(wios *stream);
+    void addPlatformDependencies(JavaLibrary *pJavaLibrary);
+};
+
+class FileHandle {
+private:
+    HANDLE FHandle;
+
+public:
+    FileHandle(std::wstring FileName);
+    ~FileHandle();
+
+    bool IsValid();
+    HANDLE GetHandle();
+};
+
+
+class FileMappingHandle {
+private:
+    HANDLE FHandle;
+
+public:
+    FileMappingHandle(HANDLE FileHandle);
+    ~FileMappingHandle();
+
+    bool IsValid();
+    HANDLE GetHandle();
+};
+
+
+class FileData {
+private:
+    LPVOID FBaseAddress;
+
+public:
+    FileData(HANDLE Handle);
+    ~FileData();
+
+    bool IsValid();
+    LPVOID GetBaseAddress();
+};
+
+
+class WindowsLibrary {
+private:
+    TString FFileName;
+
+    // Given an RVA, look up the section header that encloses it and return a
+    // pointer to its IMAGE_SECTION_HEADER
+    static PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva,
+            PIMAGE_NT_HEADERS pNTHeader);
+    static LPVOID GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader,
+            DWORD imageBase);
+    static std::vector<TString> GetImportsSection(DWORD base,
+            PIMAGE_NT_HEADERS pNTHeader);
+    static std::vector<TString> DumpPEFile(PIMAGE_DOS_HEADER dosHeader);
+
+public:
+    WindowsLibrary(const TString FileName);
+
+    std::vector<TString> GetImports();
+};
+
+
+class WindowsJob {
+private:
+    HANDLE FHandle;
+
+public:
+    WindowsJob();
+    ~WindowsJob();
+
+    HANDLE GetHandle();
+};
+
+
+class WindowsProcess : public Process {
+private:
+    bool FRunning;
+
+    PROCESS_INFORMATION FProcessInfo;
+    static WindowsJob FJob;
+
+    void Cleanup();
+    bool ReadOutput();
+
+public:
+    WindowsProcess();
+    virtual ~WindowsProcess();
+
+    virtual bool IsRunning();
+    virtual bool Terminate();
+    virtual bool Execute(const TString Application,
+            const std::vector<TString> Arguments, bool AWait = false);
+    virtual bool Wait();
+    virtual TProcessID GetProcessID();
+    virtual void SetInput(TString Value);
+    virtual std::list<TString> GetOutput();
+};
+
+#endif // WINDOWSPLATFORM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/ByteBuffer.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015, 2019, 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.
+ */
+
+#include "ByteBuffer.h"
+
+#include <stdio.h>
+
+ByteBuffer::ByteBuffer() {
+    buffer.reserve(1024);
+}
+
+ByteBuffer::~ByteBuffer() {
+}
+
+LPBYTE ByteBuffer::getPtr() {
+    return &buffer[0];
+}
+
+size_t ByteBuffer::getPos() {
+    return buffer.size();
+}
+
+void ByteBuffer::AppendString(wstring str) {
+    size_t len = (str.size() + 1) * sizeof (WCHAR);
+    AppendBytes((BYTE*) str.c_str(), len);
+}
+
+void ByteBuffer::AppendWORD(WORD word) {
+    AppendBytes((BYTE*) & word, sizeof (WORD));
+}
+
+void ByteBuffer::Align(size_t bytesNumber) {
+    size_t pos = getPos();
+    if (pos % bytesNumber) {
+        DWORD dwNull = 0;
+        size_t len = bytesNumber - pos % bytesNumber;
+        AppendBytes((BYTE*) & dwNull, len);
+    }
+}
+
+void ByteBuffer::AppendBytes(BYTE* ptr, size_t len) {
+    buffer.insert(buffer.end(), ptr, ptr + len);
+}
+
+void ByteBuffer::ReplaceWORD(size_t offset, WORD word) {
+    ReplaceBytes(offset, (BYTE*) & word, sizeof (WORD));
+}
+
+void ByteBuffer::ReplaceBytes(size_t offset, BYTE* ptr, size_t len) {
+    for (size_t i = 0; i < len; i++) {
+        buffer[offset + i] = *(ptr + i);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/ByteBuffer.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, 2019, 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.
+ */
+
+#ifndef BYTEBUFFER_H
+#define BYTEBUFFER_H
+
+#include <windows.h>
+#include <vector>
+#include <string>
+
+using namespace std;
+
+class ByteBuffer {
+public:
+    ByteBuffer();
+    ~ByteBuffer();
+
+    LPBYTE getPtr();
+    size_t getPos();
+
+    void AppendString(wstring str);
+    void AppendWORD(WORD word);
+    void AppendBytes(BYTE* ptr, size_t len);
+
+    void ReplaceWORD(size_t offset, WORD word);
+    void ReplaceBytes(size_t offset, BYTE* ptr, size_t len);
+
+    void Align(size_t bytesNumber);
+
+private:
+    vector<BYTE> buffer;
+};
+
+#endif // BYTEBUFFER_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/ErrorHandling.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <algorithm>
+
+#include "ErrorHandling.h"
+#include "Log.h"
+
+
+namespace {
+
+tstring getFilename(const SourceCodePos& pos) {
+    const std::string buf(pos.file);
+    const std::string::size_type idx = buf.find_last_of("\\/");
+    if (idx == std::string::npos) {
+        return tstrings::fromUtf8(buf);
+    }
+    return tstrings::fromUtf8(buf.substr(idx + 1));
+}
+
+void reportError(const SourceCodePos& pos, const tstring& msg) {
+    Logger::defaultLogger().log(Logger::LOG_ERROR, getFilename(pos).c_str(),
+        pos.lno, tstrings::fromUtf8(pos.func).c_str(), msg);
+}
+
+} // namespace
+
+void reportError(const SourceCodePos& pos, const std::exception& e) {
+    reportError(pos, (tstrings::any() << "Exception with message \'"
+                                        << e.what() << "\' caught").tstr());
+}
+
+
+void reportUnknownError(const SourceCodePos& pos) {
+    reportError(pos, _T("Unknown exception caught"));
+}
+
+
+std::string makeMessage(const std::exception& e, const SourceCodePos& pos) {
+    std::ostringstream printer;
+    printer << getFilename(pos) << "(" << pos.lno << ") at "
+            << pos.func << "(): "
+            << e.what();
+    return printer.str();
+}
+
+
+namespace {
+
+bool isNotSpace(int chr) {
+    return isspace(chr) == 0;
+}
+
+
+enum TrimMode {
+    TrimLeading = 0x10,
+    TrimTrailing = 0x20,
+    TrimBoth = TrimLeading | TrimTrailing
+};
+
+// Returns position of the last printed character in the given string.
+// Returns std::string::npos if nothing was printed.
+size_t printWithoutWhitespaces(std::ostream& out, const std::string& str,
+                                                            TrimMode mode) {
+    std::string::const_reverse_iterator it = str.rbegin();
+    std::string::const_reverse_iterator end = str.rend();
+
+    if (mode & TrimLeading) {
+        // skip leading whitespace
+        std::string::const_iterator entry = std::find_if(str.begin(),
+                                                str.end(), isNotSpace);
+        end = std::string::const_reverse_iterator(entry);
+    }
+
+    if (mode & TrimTrailing) {
+        // skip trailing whitespace
+        it = std::find_if(it, end, isNotSpace);
+    }
+
+    if (it == end) {
+        return std::string::npos;
+    }
+
+    const size_t pos = str.rend() - end;
+    const size_t len = end - it;
+    out.write(str.c_str() + pos, len);
+    return pos + len - 1;
+}
+
+} // namespace
+
+std::string joinErrorMessages(const std::string& a, const std::string& b) {
+    const std::string endPhraseChars(";.,:!?");
+    const std::string space(" ");
+    const std::string dotAndSpace(". ");
+
+    std::ostringstream printer;
+    printer.exceptions(std::ios::failbit | std::ios::badbit);
+
+    size_t idx = printWithoutWhitespaces(printer, a, TrimTrailing);
+    size_t extra = 0;
+    if (idx < a.size() && endPhraseChars.find(a[idx]) == std::string::npos) {
+        printer << dotAndSpace;
+        extra = dotAndSpace.size();
+    } else if (idx != std::string::npos) {
+        printer << space;
+        extra = space.size();
+    }
+
+    idx = printWithoutWhitespaces(printer, b, TrimBoth);
+
+    const std::string str = printer.str();
+
+    if (std::string::npos == idx && extra) {
+        // Nothing printed from the 'b' message. Backout delimiter string.
+        return str.substr(0, str.size() - extra);
+    }
+    return str;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/ErrorHandling.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef ErrorHandling_h
+#define ErrorHandling_h
+
+
+#include <stdexcept>
+
+#include "SourceCodePos.h"
+#include "tstrings.h"
+
+
+//
+// Exception handling helpers. Allow transparent exception logging.
+// Use as follows:
+//
+//  void foo () {
+//      JP_TRY;
+//
+//      if (!do_something()) {
+//          JP_THROW("do_something() failed");
+//      }
+//
+//      JP_CATCH_ALL;
+//  }
+//
+
+
+// Logs std::exception caught at 'pos'.
+void reportError(const SourceCodePos& pos, const std::exception& e);
+// Logs unknown exception caught at 'pos'.
+// Assumed to be called from catch (...) {}
+void reportUnknownError(const SourceCodePos& pos);
+
+std::string makeMessage(const std::exception& e, const SourceCodePos& pos);
+
+std::string joinErrorMessages(const std::string& a, const std::string& b);
+
+
+template <class Base>
+class JpError: public Base {
+public:
+    JpError(const Base& e, const SourceCodePos& pos):
+                                        Base(e), msg(::makeMessage(e, pos)) {
+    }
+
+    ~JpError() throw() {
+    }
+
+    // override Base::what()
+    const char* what() const throw() {
+        return msg.c_str();
+    }
+private:
+    // Assert Base is derived from std::exception
+    enum { isDerivedFromStdException =
+                        sizeof(static_cast<std::exception*>((Base*)0)) };
+
+    std::string msg;
+};
+
+template <class T>
+inline JpError<T> makeException(const T& obj, const SourceCodePos& p) {
+    return JpError<T>(obj, p);
+}
+
+inline JpError<std::runtime_error> makeException(
+                            const std::string& msg, const SourceCodePos& p) {
+    return JpError<std::runtime_error>(std::runtime_error(msg), p);
+}
+
+inline JpError<std::runtime_error> makeException(
+                        const tstrings::any& msg, const SourceCodePos& p) {
+    return makeException(msg.str(), p);
+}
+
+inline JpError<std::runtime_error> makeException(
+                    std::string::const_pointer msg, const SourceCodePos& p) {
+    return makeException(std::string(msg), p);
+}
+
+
+#define JP_REPORT_ERROR(e)          reportError(JP_SOURCE_CODE_POS, e)
+#define JP_REPORT_UNKNOWN_ERROR     reportUnknownError(JP_SOURCE_CODE_POS)
+
+// Redefine locally in cpp file(s) if need more handling than just reporting
+#define JP_HANDLE_ERROR(e)          JP_REPORT_ERROR(e)
+#define JP_HANDLE_UNKNOWN_ERROR     JP_REPORT_UNKNOWN_ERROR
+
+
+#define JP_TRY                              \
+        try                                 \
+        {                                   \
+            do {} while(0)
+
+#define JP_DEFAULT_CATCH_EXCEPTIONS         \
+        JP_CATCH_STD_EXCEPTION              \
+        JP_CATCH_UNKNOWN_EXCEPTION
+
+#define JP_CATCH_EXCEPTIONS                 \
+        JP_DEFAULT_CATCH_EXCEPTIONS
+
+#define JP_CATCH_ALL                        \
+        }                                   \
+        JP_CATCH_EXCEPTIONS                 \
+        do {} while(0)
+
+#define JP_CATCH_STD_EXCEPTION              \
+        catch (const std::exception& e)     \
+        {                                   \
+            JP_HANDLE_ERROR(e);             \
+        }
+
+#define JP_CATCH_UNKNOWN_EXCEPTION          \
+        catch (...)                         \
+        {                                   \
+            JP_HANDLE_UNKNOWN_ERROR;        \
+        }
+
+
+#define JP_THROW(e) throw makeException((e), JP_SOURCE_CODE_POS)
+
+#define JP_NO_THROW(expr) \
+    JP_TRY; \
+    expr; \
+    JP_CATCH_ALL
+
+#endif // #ifndef ErrorHandling_h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/FileUtils.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,709 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <memory>
+#include <algorithm>
+#include <shlwapi.h>
+
+#include "FileUtils.h"
+#include "WinErrorHandling.h"
+#include "Log.h"
+
+
+// Needed by FileUtils::isDirectoryNotEmpty
+#pragma comment(lib, "shlwapi")
+
+
+namespace FileUtils {
+
+namespace {
+
+
+tstring reservedFilenameChars() {
+    tstring buf;
+    for (char charCode = 0; charCode < 32; ++charCode) {
+        buf.append(1, charCode);
+    }
+    buf += _T("<>:\"|?*/\\");
+    return buf;
+}
+
+} // namespace
+
+bool isDirSeparator(const tstring::value_type c) {
+    return (c == '/' || c == '\\');
+}
+
+bool isFileExists(const tstring &filePath) {
+    return GetFileAttributes(filePath.c_str()) != INVALID_FILE_ATTRIBUTES;
+}
+
+namespace {
+bool isDirectoryAttrs(const DWORD attrs) {
+    return attrs != INVALID_FILE_ATTRIBUTES
+            && (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
+}
+} // namespace
+
+bool isDirectory(const tstring &filePath) {
+    return isDirectoryAttrs(GetFileAttributes(filePath.c_str()));
+}
+
+bool isDirectoryNotEmpty(const tstring &dirPath) {
+    if (!isDirectory(dirPath)) {
+        return false;
+    }
+    return FALSE == PathIsDirectoryEmpty(dirPath.c_str());
+}
+
+tstring dirname(const tstring &path) {
+    tstring::size_type pos = path.find_last_of(_T("\\/"));
+    if (pos != tstring::npos) {
+        pos = path.find_last_not_of(_T("\\/"), pos); // skip trailing slashes
+    }
+    return pos == tstring::npos ? tstring() : path.substr(0, pos + 1);
+}
+
+tstring basename(const tstring &path) {
+    const tstring::size_type pos = path.find_last_of(_T("\\/"));
+    if (pos == tstring::npos) {
+        return path;
+    }
+    return path.substr(pos + 1);
+}
+
+tstring suffix(const tstring &path) {
+    const tstring::size_type pos = path.rfind('.');
+    if (pos == tstring::npos) {
+        return tstring();
+    }
+    const tstring::size_type dirSepPos = path.find_first_of(_T("\\/"),
+                                                            pos + 1);
+    if (dirSepPos != tstring::npos) {
+        return tstring();
+    }
+    // test for '/..' and '..' cases
+    if (pos != 0 && path[pos - 1] == '.'
+                            && (pos == 1 || isDirSeparator(path[pos - 2]))) {
+        return tstring();
+    }
+    return path.substr(pos);
+}
+
+tstring combinePath(const tstring& parent, const tstring& child) {
+    if (parent.empty()) {
+        return child;
+    }
+    if (child.empty()) {
+        return parent;
+    }
+
+    tstring parentWOSlash = removeTrailingSlash(parent);
+    // also handle the case when child contains starting slash
+    bool childHasSlash = isDirSeparator(child.front());
+    tstring childWOSlash = childHasSlash ? child.substr(1) : child;
+
+    return parentWOSlash + _T("\\") + childWOSlash;
+}
+
+tstring removeTrailingSlash(const tstring& path) {
+    if (path.empty()) {
+        return path;
+    }
+    tstring::const_reverse_iterator it = path.rbegin();
+    tstring::const_reverse_iterator end = path.rend();
+
+    while (it != end && isDirSeparator(*it)) {
+        ++it;
+    }
+    return path.substr(0, end - it);
+}
+
+tstring normalizePath(tstring v) {
+    std::replace(v.begin(), v.end(), '/', '\\');
+    return tstrings::toLower(v);
+}
+
+namespace {
+
+bool createNewFile(const tstring& path) {
+    HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
+            FILE_ATTRIBUTE_NORMAL, NULL);
+    // if the file exists => h == INVALID_HANDLE_VALUE & GetLastError
+    // returns ERROR_FILE_EXISTS
+    if (h != INVALID_HANDLE_VALUE) {
+        CloseHandle(h);
+        LOG_TRACE(tstrings::any() << "Created [" << path << "] file");
+        return true;
+    }
+    return false;
+}
+
+} // namespace
+
+tstring createTempFile(const tstring &prefix, const tstring &suffix,
+        const tstring &path) {
+    const tstring invalidChars = reservedFilenameChars();
+
+    if (prefix.find_first_of(invalidChars) != tstring::npos) {
+        JP_THROW(tstrings::any() << "Illegal characters in prefix=" << prefix);
+    }
+
+    if (suffix.find_first_of(invalidChars) != tstring::npos) {
+        JP_THROW(tstrings::any() << "Illegal characters in suffix=" << suffix);
+    }
+
+    int rnd = (int)GetTickCount();
+
+    // do no more than 100 attempts
+    for (int i=0; i<100; i++) {
+        const tstring filePath = mkpath() << path << (prefix
+                + (tstrings::any() << (rnd + i)).tstr() + suffix);
+        if (createNewFile(filePath)) {
+            return filePath;
+        }
+    }
+
+    // 100 attempts failed
+    JP_THROW(tstrings::any() << "createTempFile("  << prefix << ", "
+                                                    << suffix << ", "
+                                                    << path << ") failed");
+}
+
+tstring createTempDirectory(const tstring &prefix, const tstring &suffix,
+        const tstring &basedir) {
+    const tstring filePath = createTempFile(prefix, suffix, basedir);
+    // delete the file and create directory with the same name
+    deleteFile(filePath);
+    createDirectory(filePath);
+    return filePath;
+}
+
+tstring createUniqueFile(const tstring &prototype) {
+    if (createNewFile(prototype)) {
+        return prototype;
+    }
+
+    return createTempFile(replaceSuffix(basename(prototype)),
+            suffix(prototype), dirname(prototype));
+}
+
+namespace {
+
+void createDir(const tstring path, LPSECURITY_ATTRIBUTES saAttr,
+        tstring_array* createdDirs=0) {
+    if (CreateDirectory(path.c_str(), saAttr)) {
+        LOG_TRACE(tstrings::any() << "Created [" << path << "] directory");
+        if (createdDirs) {
+            createdDirs->push_back(removeTrailingSlash(path));
+        }
+    } else {
+        const DWORD createDirectoryErr = GetLastError();
+        // if saAttr is specified, fail even if the directory exists
+        if (saAttr != NULL || !isDirectory(path)) {
+            JP_THROW(SysError(tstrings::any() << "CreateDirectory("
+                << path << ") failed", CreateDirectory, createDirectoryErr));
+        }
+    }
+}
+
+}
+
+void createDirectory(const tstring &path, tstring_array* createdDirs) {
+    const tstring dirPath = removeTrailingSlash(path) + _T("\\");
+
+    tstring::size_type pos = dirPath.find_first_of(_T("\\/"));
+    while (pos != tstring::npos) {
+        const tstring subdirPath = dirPath.substr(0, pos + 1);
+        createDir(subdirPath, NULL, createdDirs);
+        pos = dirPath.find_first_of(_T("\\/"), pos + 1);
+    }
+}
+
+
+void copyFile(const tstring& fromPath, const tstring& toPath,
+        bool failIfExists) {
+    createDirectory(dirname(toPath));
+    if (!CopyFile(fromPath.c_str(), toPath.c_str(),
+            (failIfExists ? TRUE : FALSE))) {
+        JP_THROW(SysError(tstrings::any()
+                << "CopyFile(" << fromPath << ", " << toPath << ", "
+                << failIfExists << ") failed", CopyFile));
+    }
+    LOG_TRACE(tstrings::any() << "Copied [" << fromPath << "] file to ["
+            << toPath << "]");
+}
+
+
+namespace {
+
+void moveFileImpl(const tstring& fromPath, const tstring& toPath,
+        DWORD flags) {
+    const bool isDir = isDirectory(fromPath);
+    if (!MoveFileEx(fromPath.c_str(), toPath.empty() ? NULL : toPath.c_str(),
+            flags)) {
+        JP_THROW(SysError(tstrings::any() << "MoveFileEx(" << fromPath
+                << ", " << toPath << ", " << flags << ") failed", MoveFileEx));
+    }
+
+    const bool onReboot = 0 != (flags & MOVEFILE_DELAY_UNTIL_REBOOT);
+
+    const LPCTSTR label = isDir ? _T("folder") : _T("file");
+
+    tstrings::any msg;
+    if (!toPath.empty()) {
+        if (onReboot) {
+            msg << "Move";
+        } else {
+            msg << "Moved";
+        }
+        msg << " '" << fromPath << "' " << label << " to '" << toPath << "'";
+    } else {
+        if (onReboot) {
+            msg << "Delete";
+        } else {
+            msg << "Deleted";
+        }
+        msg << " '" << fromPath << "' " << label;
+    }
+    if (onReboot) {
+        msg << " on reboot";
+    }
+    LOG_TRACE(msg);
+}
+
+} // namespace
+
+
+void moveFile(const tstring& fromPath, const tstring& toPath,
+        bool failIfExists) {
+    createDirectory(dirname(toPath));
+
+    DWORD flags = MOVEFILE_COPY_ALLOWED;
+    if (!failIfExists) {
+        flags |= MOVEFILE_REPLACE_EXISTING;
+    }
+
+    moveFileImpl(fromPath, toPath, flags);
+}
+
+void deleteFile(const tstring &path)
+{
+    if (!deleteFile(path, std::nothrow)) {
+        JP_THROW(SysError(tstrings::any()
+                << "DeleteFile(" << path << ") failed", DeleteFile));
+    }
+}
+
+namespace {
+
+bool notFound(const DWORD status=GetLastError()) {
+    return status == ERROR_FILE_NOT_FOUND || status == ERROR_PATH_NOT_FOUND;
+}
+
+bool deleteFileImpl(const std::nothrow_t &, const tstring &path) {
+    const bool deleted = (DeleteFile(path.c_str()) != 0);
+    if (deleted) {
+        LOG_TRACE(tstrings::any() << "Deleted [" << path << "] file");
+        return true;
+    }
+    return notFound();
+}
+
+} // namespace
+
+bool deleteFile(const tstring &path, const std::nothrow_t &) throw()
+{
+    bool deleted = deleteFileImpl(std::nothrow, path);
+    const DWORD status = GetLastError();
+    if (!deleted && status == ERROR_ACCESS_DENIED) {
+        DWORD attrs = GetFileAttributes(path.c_str());
+        SetLastError(status);
+        if (attrs == INVALID_FILE_ATTRIBUTES) {
+            return false;
+        }
+        if (attrs & FILE_ATTRIBUTE_READONLY) {
+            // DeleteFile() failed because file is R/O.
+            // Remove R/O attribute and retry DeleteFile().
+            attrs &= ~FILE_ATTRIBUTE_READONLY;
+            if (SetFileAttributes(path.c_str(), attrs)) {
+                LOG_TRACE(tstrings::any() << "Discarded R/O attribute from ["
+                                                        << path << "] file");
+                deleted = deleteFileImpl(std::nothrow, path);
+            } else {
+                LOG_WARNING(SysError(tstrings::any()
+                            << "Failed to discard R/O attribute from ["
+                            << path << "] file. File will not be deleted",
+                            SetFileAttributes).what());
+                SetLastError(status);
+            }
+        }
+    }
+
+    return deleted || notFound();
+}
+
+void deleteDirectory(const tstring &path)
+{
+    if (!deleteDirectory(path, std::nothrow)) {
+        JP_THROW(SysError(tstrings::any()
+                << "RemoveDirectory(" << path << ") failed", RemoveDirectory));
+    }
+}
+
+bool deleteDirectory(const tstring &path, const std::nothrow_t &) throw()
+{
+    const bool deleted = (RemoveDirectory(path.c_str()) != 0);
+    if (deleted) {
+        LOG_TRACE(tstrings::any() << "Deleted [" << path << "] directory");
+    }
+    return deleted || notFound();
+}
+
+namespace {
+
+class DeleteFilesCallback: public DirectoryCallback {
+public:
+    explicit DeleteFilesCallback(bool ff): failfast(ff), failed(false) {
+    }
+
+    virtual bool onFile(const tstring& path) {
+        if (failfast) {
+            deleteFile(path);
+        } else {
+            updateStatus(deleteFile(path, std::nothrow));
+        }
+        return true;
+    }
+
+    bool good() const {
+        return !failed;
+    }
+
+protected:
+    void updateStatus(bool success) {
+        if (!success) {
+            failed = true;
+        }
+    }
+
+    const bool failfast;
+private:
+    bool failed;
+};
+
+class DeleteAllCallback: public DeleteFilesCallback {
+public:
+    explicit DeleteAllCallback(bool failfast): DeleteFilesCallback(failfast) {
+    }
+
+    virtual bool onDirectory(const tstring& path) {
+        if (failfast) {
+            deleteDirectoryRecursive(path);
+        } else {
+            updateStatus(deleteDirectoryRecursive(path, std::nothrow));
+        }
+        return true;
+    }
+};
+
+
+class BatchDeleter {
+    const tstring dirPath;
+    bool recursive;
+public:
+    explicit BatchDeleter(const tstring& path): dirPath(path) {
+        deleteSubdirs(false);
+    }
+
+    BatchDeleter& deleteSubdirs(bool v) {
+        recursive = v;
+        return *this;
+    }
+
+    void execute() const {
+        if (!isFileExists(dirPath)) {
+            return;
+        }
+        iterateDirectory(true /* fail fast */);
+        if (recursive) {
+            deleteDirectory(dirPath);
+        }
+    }
+
+    bool execute(const std::nothrow_t&) const {
+        if (!isFileExists(dirPath)) {
+            return true;
+        }
+
+        if (!isDirectory(dirPath)) {
+            return false;
+        }
+
+        JP_TRY;
+        if (!iterateDirectory(false /* ignore errors */)) {
+            return false;
+        }
+        if (recursive) {
+            return deleteDirectory(dirPath, std::nothrow);
+        }
+        return true;
+        JP_CATCH_ALL;
+
+        return false;
+    }
+
+private:
+    bool iterateDirectory(bool failfast) const {
+        std::unique_ptr<DeleteFilesCallback> callback;
+        if (recursive) {
+            callback = std::unique_ptr<DeleteFilesCallback>(
+                                            new DeleteAllCallback(failfast));
+        } else {
+            callback = std::unique_ptr<DeleteFilesCallback>(
+                                            new DeleteFilesCallback(failfast));
+        }
+
+        FileUtils::iterateDirectory(dirPath, *callback);
+        return callback->good();
+    }
+};
+
+} // namespace
+
+void deleteFilesInDirectory(const tstring &dirPath) {
+    BatchDeleter(dirPath).execute();
+}
+
+bool deleteFilesInDirectory(const tstring &dirPath,
+                                            const std::nothrow_t &) throw() {
+    return BatchDeleter(dirPath).execute(std::nothrow);
+}
+
+void deleteDirectoryRecursive(const tstring &dirPath) {
+    BatchDeleter(dirPath).deleteSubdirs(true).execute();
+}
+
+bool deleteDirectoryRecursive(const tstring &dirPath,
+                                            const std::nothrow_t &) throw() {
+    return BatchDeleter(dirPath).deleteSubdirs(true).execute(std::nothrow);
+}
+
+namespace {
+
+struct FindFileDeleter {
+    typedef HANDLE pointer;
+
+    void operator()(HANDLE h) {
+        if (h && h != INVALID_HANDLE_VALUE) {
+            FindClose(h);
+        }
+    }
+};
+
+typedef std::unique_ptr<HANDLE, FindFileDeleter> UniqueFindFileHandle;
+
+}; // namesace
+void iterateDirectory(const tstring &dirPath, DirectoryCallback& callback)
+{
+    const tstring searchString = combinePath(dirPath, _T("*"));
+    WIN32_FIND_DATA findData;
+    UniqueFindFileHandle h(FindFirstFile(searchString.c_str(), &findData));
+    if (h.get() == INVALID_HANDLE_VALUE) {
+        // GetLastError() == ERROR_FILE_NOT_FOUND is OK
+        // - no files in the directory
+        // ERROR_PATH_NOT_FOUND is returned
+        // if the parent directory does not exist
+        if (GetLastError() != ERROR_FILE_NOT_FOUND) {
+            JP_THROW(SysError(tstrings::any() << "FindFirstFile("
+                    << dirPath << ") failed", FindFirstFile));
+        }
+        return;
+    }
+
+    do {
+        const tstring fname(findData.cFileName);
+        const tstring filePath = combinePath(dirPath, fname);
+        if (!isDirectoryAttrs(findData.dwFileAttributes)) {
+            if (!callback.onFile(filePath)) {
+                return;
+            }
+        } else if (fname != _T(".") && fname != _T("..")) {
+            if (!callback.onDirectory(filePath)) {
+                return;
+            }
+        }
+    } while (FindNextFile(h.get(), &findData));
+
+    // expect GetLastError() == ERROR_NO_MORE_FILES
+    if (GetLastError() != ERROR_NO_MORE_FILES) {
+        JP_THROW(SysError(tstrings::any() << "FindNextFile("
+                << dirPath << ") failed", FindNextFile));
+    }
+}
+
+
+tstring replaceSuffix(const tstring& path, const tstring& newSuffix) {
+    return (path.substr(0, path.size() - suffix(path).size()) + newSuffix);
+}
+
+
+DirectoryIterator& DirectoryIterator::findItems(tstring_array& v) {
+    if (!isDirectory(root)) {
+        return *this;
+    }
+
+    iterateDirectory(root, *this);
+    v.insert(v.end(), items.begin(), items.end());
+    items = tstring_array();
+    return *this;
+}
+
+bool DirectoryIterator::onFile(const tstring& path) {
+    if (theWithFiles) {
+        items.push_back(path);
+    }
+    return true;
+}
+
+bool DirectoryIterator::onDirectory(const tstring& path) {
+    if (theWithFolders) {
+        items.push_back(path);
+    }
+    if (theRecurse) {
+        DirectoryIterator(path).recurse(theRecurse)
+                .withFiles(theWithFiles)
+                .withFolders(theWithFolders)
+                .findItems(items);
+    }
+    return true;
+}
+
+
+namespace {
+
+struct DeleterFunctor {
+    // Order of items in the following enum is important!
+    // It controls order in which items of particular type will be deleted.
+    // See Deleter::execute().
+    enum {
+        File,
+        FilesInDirectory,
+        RecursiveDirectory,
+        EmptyDirectory
+    };
+
+    void operator () (const Deleter::Path& path) const {
+        switch (path.second) {
+#define DELETE_SOME(o, f)\
+        case o:\
+            f(path.first, std::nothrow);\
+            break
+
+        DELETE_SOME(File, deleteFile);
+        DELETE_SOME(EmptyDirectory, deleteDirectory);
+        DELETE_SOME(FilesInDirectory, deleteFilesInDirectory);
+        DELETE_SOME(RecursiveDirectory, deleteDirectoryRecursive);
+
+#undef DELETE_SOME
+        default:
+            break;
+        }
+    }
+};
+
+} // namespace
+
+void Deleter::execute() {
+    Paths tmp;
+    tmp.swap(paths);
+
+    // Reorder items to delete.
+    std::stable_sort(tmp.begin(), tmp.end(), [] (const Paths::value_type& a,
+                                                const Paths::value_type& b) {
+        return a.second < b.second;
+    });
+
+    std::for_each(tmp.begin(), tmp.end(), DeleterFunctor());
+}
+
+Deleter& Deleter::appendFile(const tstring& path) {
+    paths.push_back(std::make_pair(path, DeleterFunctor::File));
+    return *this;
+}
+
+Deleter& Deleter::appendEmptyDirectory(const Directory& dir) {
+     tstring path =  normalizePath(removeTrailingSlash(dir));
+     const tstring parent = normalizePath(removeTrailingSlash(dir.parent));
+     while(parent != path) {
+         appendEmptyDirectory(path);
+         path = dirname(path);
+     }
+
+    return *this;
+}
+
+Deleter& Deleter::appendEmptyDirectory(const tstring& path) {
+    paths.push_back(std::make_pair(path, DeleterFunctor::EmptyDirectory));
+    return *this;
+}
+
+Deleter& Deleter::appendAllFilesInDirectory(const tstring& path) {
+    paths.push_back(std::make_pair(path, DeleterFunctor::FilesInDirectory));
+    return *this;
+}
+
+Deleter& Deleter::appendRecursiveDirectory(const tstring& path) {
+    paths.push_back(std::make_pair(path, DeleterFunctor::RecursiveDirectory));
+    return *this;
+}
+
+
+FileWriter::FileWriter(const tstring& path): dstPath(path) {
+    tmpFile = FileUtils::createTempFile(_T("jds"), _T(".tmp"),
+            FileUtils::dirname(path));
+
+    cleaner.appendFile(tmpFile);
+
+    // we want to get exception on error
+    tmp.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+    tmp.open(tmpFile, std::ios::binary | std::ios::trunc);
+}
+
+FileWriter& FileWriter::write(const void* buf, size_t bytes) {
+    tmp.write(static_cast<const char*>(buf), bytes);
+    return *this;
+}
+
+void FileWriter::finalize() {
+    tmp.close();
+
+    FileUtils::moveFile(tmpFile, dstPath, false);
+
+    // cancel file deletion
+    cleaner.cancel();
+}
+
+} //  namespace FileUtils
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/FileUtils.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef FILEUTILS_H
+#define FILEUTILS_H
+
+
+#include <fstream>
+#include "SysInfo.h"
+
+
+namespace FileUtils {
+
+    // Returns 'true' if the given character is a path separator.
+    bool isDirSeparator(const tstring::value_type c);
+
+    // checks if the file or directory exists
+    bool isFileExists(const tstring &filePath);
+
+    // checks is the specified file is a directory
+    // returns false if the path does not exist
+    bool isDirectory(const tstring &filePath);
+
+    // checks if the specified directory is not empty
+    // returns true if the path is an existing directory and
+    // it contains at least one file other than "." or "..".
+    bool isDirectoryNotEmpty(const tstring &dirPath);
+
+    // returns directory part of the path.
+    // returns empty string if the path contains only filename.
+    // if the path ends with slash/backslash,
+    // returns removeTrailingSlashes(path).
+    tstring dirname(const tstring &path);
+
+    // returns basename part of the path
+    // if the path ends with slash/backslash, returns empty string.
+    tstring basename(const tstring &path);
+
+    /**
+     * Translates forward slashes to back slashes and returns lower case version
+     * of the given string.
+     */
+    tstring normalizePath(tstring v);
+
+    // Returns suffix of the path. If the given path has a suffix the first
+    // character of the return value is '.'.
+    // Otherwise return value if empty string.
+    tstring suffix(const tstring &path);
+
+    // combines two strings into a path
+    tstring combinePath(const tstring& parent, const tstring& child);
+
+    // removes trailing slashes and backslashes in the path if any
+    tstring removeTrailingSlash(const tstring& path);
+
+    // Creates a file with unique name in the specified base directory,
+    // throws an exception if operation fails
+    // path is constructed as <prefix><random number><suffix>.
+    // The function fails and throws exception if 'path' doesn't exist.
+    tstring createTempFile(const tstring &prefix = _T(""),
+            const tstring &suffix = _T(".tmp"),
+            const tstring &path=SysInfo::getTempDir());
+
+    // Creates a directory with unique name in the specified base directory,
+    // throws an exception if operation fails
+    // path is constructed as <prefix><random number><suffix>
+    // The function fails and throws exception if 'path' doesn't exist.
+    tstring createTempDirectory(const tstring &prefix = _T(""),
+            const tstring &suffix = _T(".tmp"),
+            const tstring &basedir=SysInfo::getTempDir());
+
+    // If the file referenced with "prototype" parameter DOES NOT exist,
+    // the return value is the given path. No new files created.
+    // Otherwise the function creates another file in the same directory as
+    // the given file with the same suffix and with the basename from the
+    // basename of the given file with some random chars appended to ensure
+    // created file is unique.
+    tstring createUniqueFile(const tstring &prototype);
+
+    // Creates directory and subdirectories if don't exist.
+    // Currently supports only "standard" path like "c:\bla-bla"
+    // If 'createdDirs' parameter is not NULL, the given array is appended with
+    // all subdirectories created by this function call.
+    void createDirectory(const tstring &path, tstring_array* createdDirs=0);
+
+    // copies file from fromPath to toPath.
+    // Creates output directory if doesn't exist.
+    void copyFile(const tstring& fromPath, const tstring& toPath,
+            bool failIfExists);
+
+    // moves file from fromPath to toPath.
+    // Creates output directory if doesn't exist.
+    void moveFile(const tstring& fromPath, const tstring& toPath,
+            bool failIfExists);
+
+    // Throws exception if fails to delete specified 'path'.
+    // Exits normally if 'path' doesn't exist or it has been deleted.
+    // Attempts to strip R/O attribute if delete fails and retry delete.
+    void deleteFile(const tstring &path);
+    // Returns 'false' if fails to delete specified 'path'.
+    // Returns 'true' if 'path' doesn't exist or it has been deleted.
+    // Attempts to strip R/O attribute if delete fails and retry delete.
+    bool deleteFile(const tstring &path, const std::nothrow_t &) throw();
+
+    // Like deleteFile(), but applies to directories.
+    void deleteDirectory(const tstring &path);
+    bool deleteDirectory(const tstring &path, const std::nothrow_t &) throw();
+
+    // Deletes all files (not subdirectories) from the specified directory.
+    // Exits normally if all files in 'dirPath' have been deleted or if
+    // 'dirPath' doesn't exist.
+    // Throws exception if 'dirPath' references existing file system object
+    // which is not a directory or when the first failure of file delete
+    // occurs.
+    void deleteFilesInDirectory(const tstring &dirPath);
+    // Deletes all files (not subdirectories) from the specified directory.
+    // Returns 'true' normally if all files in 'dirPath' have been deleted or
+    // if 'dirPath' doesn't exist.
+    // Returns 'false' if 'dirPath' references existing file system object
+    // which is not a directory or if failed to delete one ore more files in
+    // 'dirPath' directory.
+    // Doesn't abort iteration over files if the given directory after the
+    // first failure to delete a file.
+    bool deleteFilesInDirectory(const tstring &dirPath,
+            const std::nothrow_t &) throw();
+    // Like deleteFilesInDirectory, but deletes subdirectories as well
+    void deleteDirectoryRecursive(const tstring &dirPath);
+    bool deleteDirectoryRecursive(const tstring &dirPath,
+            const std::nothrow_t &) throw();
+
+    class DirectoryCallback {
+    public:
+        virtual ~DirectoryCallback() {};
+
+        virtual bool onFile(const tstring& path) {
+            return true;
+        }
+        virtual bool onDirectory(const tstring& path) {
+            return true;
+        }
+    };
+
+    // Calls the given callback for every file and subdirectory of
+    // the given directory.
+    void iterateDirectory(const tstring &dirPath, DirectoryCallback& callback);
+
+    /**
+     * Replace file suffix, example replaceSuffix("file/path.txt", ".csv")
+     * @param path file path to replace suffix
+     * @param suffix new suffix for path
+     * @return return file path with new suffix
+     */
+    tstring replaceSuffix(const tstring& path, const tstring& suffix=tstring());
+
+    class DirectoryIterator: DirectoryCallback {
+    public:
+        DirectoryIterator(const tstring& root=tstring()): root(root) {
+            recurse().withFiles().withFolders();
+        }
+
+        DirectoryIterator& recurse(bool v=true) {
+            theRecurse = v;
+            return *this;
+        }
+
+        DirectoryIterator& withFiles(bool v=true) {
+            theWithFiles = v;
+            return *this;
+        }
+
+        DirectoryIterator& withFolders(bool v=true) {
+            theWithFolders = v;
+            return *this;
+        }
+
+        tstring_array findItems() {
+            tstring_array reply;
+            findItems(reply);
+            return reply;
+        }
+
+        DirectoryIterator& findItems(tstring_array& v);
+
+    private:
+        virtual bool onFile(const tstring& path);
+        virtual bool onDirectory(const tstring& path);
+
+    private:
+        bool theRecurse;
+        bool theWithFiles;
+        bool theWithFolders;
+        tstring root;
+        tstring_array items;
+    };
+
+    // Returns array of all the files/sub-folders from the given directory,
+    // empty array if basedir is not a directory. The returned
+    // array is ordered from top down (i.e. dirs are listed first followed
+    // by subfolders and files).
+    // Order of subfolders and files is undefined
+    // but usually they are sorted by names.
+    inline tstring_array listAllContents(const tstring& basedir) {
+        return DirectoryIterator(basedir).findItems();
+    }
+
+    // Helper to construct path from multiple components.
+    //
+    // Sample usage:
+    //  Construct "c:\Program Files\Java" string from three components
+    //
+    //  tstring path = FileUtils::mkpath()  << _T("c:")
+    //                                      << _T("Program Files")
+    //                                      << _T("Java");
+    //
+    class mkpath {
+    public:
+        operator const tstring& () const {
+            return path;
+        }
+
+        mkpath& operator << (const tstring& p) {
+            path = combinePath(path, p);
+            return *this;
+        }
+
+        // mimic std::string
+        const tstring::value_type* c_str() const {
+            return path.c_str();
+        }
+    private:
+        tstring path;
+    };
+
+    struct Directory {
+        Directory() {
+        }
+
+        Directory(const tstring &parent,
+                const tstring &subdir) : parent(parent), subdir(subdir)  {
+        }
+
+        operator tstring () const {
+            return getPath();
+        }
+
+        tstring getPath() const {
+            return combinePath(parent, subdir);
+        }
+
+        bool empty() const {
+            return (parent.empty() && subdir.empty());
+        }
+
+        tstring parent;
+        tstring subdir;
+    };
+
+    // Deletes list of files and directories in batch mode.
+    // Registered files and directories are deleted when destructor is called.
+    // Order or delete operations is following:
+    //  - delete items registered with appendFile() calls;
+    //  - delete items registered with appendAllFilesInDirectory() calls;
+    //  - delete items registered with appendRecursiveDirectory() calls;
+    //  - delete items registered with appendEmptyDirectory() calls.
+    class Deleter {
+    public:
+        Deleter() {
+        }
+
+        ~Deleter() {
+            execute();
+        }
+
+        typedef std::pair<tstring, int> Path;
+        typedef std::vector<Path> Paths;
+
+        /**
+         * Appends all records from the given deleter Deleter into this Deleter
+         * instance. On success array with records in the passed in Deleter
+         * instance is emptied.
+         */
+        Deleter& appendFrom(Deleter& other) {
+            Paths tmp(paths);
+            tmp.insert(tmp.end(), other.paths.begin(), other.paths.end());
+            Paths empty;
+            other.paths.swap(empty);
+            paths.swap(tmp);
+            return *this;
+        }
+
+        // Schedule file for deletion.
+        Deleter& appendFile(const tstring& path);
+
+        // Schedule files for deletion.
+        template <class It>
+        Deleter& appendFiles(It b, It e) {
+            for (It it = b; it != e; ++it) {
+                appendFile(*it);
+            }
+            return *this;
+        }
+
+        // Schedule files for deletion in the given directory.
+        template <class It>
+        Deleter& appendFiles(const tstring& dirname, It b, It e) {
+            for (It it = b; it != e; ++it) {
+                appendFile(FileUtils::mkpath() << dirname << *it);
+            }
+            return *this;
+        }
+
+        // Schedule empty directory for deletion with empty roots
+        // (up to Directory.parent).
+        Deleter& appendEmptyDirectory(const Directory& dir);
+
+        // Schedule empty directory for deletion without roots.
+        // This is a particular case of
+        // appendEmptyDirectory(const Directory& dir)
+        // with Directory(dirname(path), basename(path)).
+        Deleter& appendEmptyDirectory(const tstring& path);
+
+        // Schedule all file from the given directory for deletion.
+        Deleter& appendAllFilesInDirectory(const tstring& path);
+
+        // Schedule directory for recursive deletion.
+        Deleter& appendRecursiveDirectory(const tstring& path);
+
+        void cancel() {
+            paths.clear();
+        }
+
+        // Deletes scheduled files and directories. After this function
+        // is called internal list of scheduled items is emptied.
+        void execute();
+
+    private:
+        Paths paths;
+    };
+
+
+    /**
+     * Helper to write chunks of data into binary file.
+     * Creates temporary file in the same folder with destination file.
+     * All subsequent requests to save data chunks are redirected to temporary
+     * file. finalize() method closes temporary file stream and renames
+     * temporary file.
+     * If finalize() method is not called, temporary file is deleted in
+     * ~FileWriter(), destination file is not touched.
+     */
+    class FileWriter {
+    public:
+        explicit FileWriter(const tstring& path);
+
+        FileWriter& write(const void* buf, size_t bytes);
+
+        template <class Ctnr>
+        FileWriter& write(const Ctnr& buf) {
+            return write(buf.data(),
+                            buf.size() * sizeof(typename Ctnr::value_type));
+        }
+
+        void finalize();
+
+    private:
+        // Not accessible by design!
+        FileWriter& write(const std::wstring& str);
+
+    private:
+        tstring tmpFile;
+        Deleter cleaner;
+        std::ofstream tmp;
+        tstring dstPath;
+    };
+} // FileUtils
+
+#endif // FILEUTILS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/IconSwap.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2012, 2019, 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.
+ */
+
+#include <stdio.h>
+#include <windows.h>
+#include <stdlib.h>
+#include <string>
+#include <malloc.h>
+
+using namespace std;
+
+// http://msdn.microsoft.com/en-us/library/ms997538.aspx
+
+typedef struct _ICONDIRENTRY {
+    BYTE bWidth;
+    BYTE bHeight;
+    BYTE bColorCount;
+    BYTE bReserved;
+    WORD wPlanes;
+    WORD wBitCount;
+    DWORD dwBytesInRes;
+    DWORD dwImageOffset;
+} ICONDIRENTRY, * LPICONDIRENTRY;
+
+typedef struct _ICONDIR {
+    WORD idReserved;
+    WORD idType;
+    WORD idCount;
+    ICONDIRENTRY idEntries[1];
+} ICONDIR, * LPICONDIR;
+
+// #pragmas are used here to insure that the structure's
+// packing in memory matches the packing of the EXE or DLL.
+#pragma pack(push)
+#pragma pack(2)
+
+typedef struct _GRPICONDIRENTRY {
+    BYTE bWidth;
+    BYTE bHeight;
+    BYTE bColorCount;
+    BYTE bReserved;
+    WORD wPlanes;
+    WORD wBitCount;
+    DWORD dwBytesInRes;
+    WORD nID;
+} GRPICONDIRENTRY, * LPGRPICONDIRENTRY;
+#pragma pack(pop)
+
+#pragma pack(push)
+#pragma pack(2)
+
+typedef struct _GRPICONDIR {
+    WORD idReserved;
+    WORD idType;
+    WORD idCount;
+    GRPICONDIRENTRY idEntries[1];
+} GRPICONDIR, * LPGRPICONDIR;
+#pragma pack(pop)
+
+void PrintError() {
+    LPVOID message = NULL;
+    DWORD error = GetLastError();
+
+    if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
+            | FORMAT_MESSAGE_FROM_SYSTEM
+            | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
+            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+            (LPTSTR) & message, 0, NULL) != 0) {
+        printf("%S", (LPTSTR) message);
+        LocalFree(message);
+    }
+}
+
+// Note: We do not check here that iconTarget is valid icon.
+// Java code will already do this for us.
+
+bool ChangeIcon(wstring iconTarget, wstring launcher) {
+    WORD language = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
+
+    HANDLE icon = CreateFile(iconTarget.c_str(), GENERIC_READ, 0, NULL,
+            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (icon == INVALID_HANDLE_VALUE) {
+        PrintError();
+        return false;
+    }
+
+    // Reading .ICO file
+    WORD idReserved, idType, idCount;
+
+    DWORD dwBytesRead;
+    ReadFile(icon, &idReserved, sizeof (WORD), &dwBytesRead, NULL);
+    ReadFile(icon, &idType, sizeof (WORD), &dwBytesRead, NULL);
+    ReadFile(icon, &idCount, sizeof (WORD), &dwBytesRead, NULL);
+
+    LPICONDIR lpid = (LPICONDIR) malloc(
+            sizeof (ICONDIR) + (sizeof (ICONDIRENTRY) * (idCount - 1)));
+    if (lpid == NULL) {
+        CloseHandle(icon);
+        printf("Error: Failed to allocate memory\n");
+        return false;
+    }
+
+    lpid->idReserved = idReserved;
+    lpid->idType = idType;
+    lpid->idCount = idCount;
+
+    ReadFile(icon, &lpid->idEntries[0], sizeof (ICONDIRENTRY) * lpid->idCount,
+            &dwBytesRead, NULL);
+
+    LPGRPICONDIR lpgid = (LPGRPICONDIR) malloc(
+            sizeof (GRPICONDIR) + (sizeof (GRPICONDIRENTRY) * (idCount - 1)));
+    if (lpid == NULL) {
+        CloseHandle(icon);
+        free(lpid);
+        printf("Error: Failed to allocate memory\n");
+        return false;
+    }
+
+    lpgid->idReserved = idReserved;
+    lpgid->idType = idType;
+    lpgid->idCount = idCount;
+
+    for (int i = 0; i < lpgid->idCount; i++) {
+        lpgid->idEntries[i].bWidth = lpid->idEntries[i].bWidth;
+        lpgid->idEntries[i].bHeight = lpid->idEntries[i].bHeight;
+        lpgid->idEntries[i].bColorCount = lpid->idEntries[i].bColorCount;
+        lpgid->idEntries[i].bReserved = lpid->idEntries[i].bReserved;
+        lpgid->idEntries[i].wPlanes = lpid->idEntries[i].wPlanes;
+        lpgid->idEntries[i].wBitCount = lpid->idEntries[i].wBitCount;
+        lpgid->idEntries[i].dwBytesInRes = lpid->idEntries[i].dwBytesInRes;
+        lpgid->idEntries[i].nID = i + 1;
+    }
+
+    // Store images in .EXE
+    HANDLE update = BeginUpdateResource(launcher.c_str(), FALSE);
+    if (update == NULL) {
+        free(lpid);
+        free(lpgid);
+        CloseHandle(icon);
+        PrintError();
+        return false;
+    }
+
+    for (int i = 0; i < lpid->idCount; i++) {
+        LPBYTE lpBuffer = (LPBYTE) malloc(lpid->idEntries[i].dwBytesInRes);
+        SetFilePointer(icon, lpid->idEntries[i].dwImageOffset,
+                NULL, FILE_BEGIN);
+        ReadFile(icon, lpBuffer, lpid->idEntries[i].dwBytesInRes,
+                &dwBytesRead, NULL);
+        if (!UpdateResource(update, RT_ICON,
+                MAKEINTRESOURCE(lpgid->idEntries[i].nID),
+                language, &lpBuffer[0], lpid->idEntries[i].dwBytesInRes)) {
+            free(lpBuffer);
+            free(lpid);
+            free(lpgid);
+            CloseHandle(icon);
+            PrintError();
+            return false;
+        }
+        free(lpBuffer);
+    }
+
+    free(lpid);
+    CloseHandle(icon);
+
+    if (!UpdateResource(update, RT_GROUP_ICON, MAKEINTRESOURCE(1),
+            language, &lpgid[0], (sizeof (WORD) * 3)
+            + (sizeof (GRPICONDIRENTRY) * lpgid->idCount))) {
+        free(lpgid);
+        PrintError();
+        return false;
+    }
+
+    free(lpgid);
+
+    if (EndUpdateResource(update, FALSE) == FALSE) {
+        PrintError();
+        return false;
+    }
+
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/IconSwap.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, 2019, 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.
+ */
+
+#ifndef ICONSWAP_H
+#define ICONSWAP_H
+
+#include <string>
+
+using namespace std;
+
+bool ChangeIcon(wstring iconTarget, wstring launcher);
+
+#endif // ICONSWAP_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/Log.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include "Log.h"
+#include "SysInfo.h"
+#include "FileUtils.h"
+
+
+namespace {
+    //
+    // IMPORTANT: Static objects with non-trivial constructors are NOT allowed
+    // in logger module. Allocate buffers only and do lazy initialization of
+    // globals in Logger::getDefault().
+    //
+    // Logging subsystem is used almost in every module, and logging API can be
+    // called from constructors of static objects in various modules. As
+    // ordering of static objects initialization between modules is undefined,
+    // this means some module may call logging api before logging static
+    // variables are initialized if any. This will result in AV. To avoid such
+    // use cases keep logging module free from static variables that require
+    // initialization with functions called by CRT.
+    //
+
+    // by default log everything
+    const Logger::LogLevel defaultLogLevel = Logger::LOG_TRACE;
+
+    char defaultLogAppenderMemory[sizeof(StderrLogAppender)] = {};
+
+    char defaultLoggerMemory[sizeof(Logger)] = {};
+
+    NopLogAppender nopLogApender;
+
+    LPCTSTR getLogLevelStr(Logger::LogLevel level) {
+        switch (level) {
+        case Logger::LOG_TRACE:
+            return _T("TRACE");
+        case Logger::LOG_INFO:
+            return _T("INFO");
+        case Logger::LOG_WARNING:
+            return _T("WARNING");
+        case Logger::LOG_ERROR:
+            return _T("ERROR");
+        }
+        return _T("UNKNOWN");
+    }
+
+    tstring retrieveModuleName() {
+        try {
+            return FileUtils::basename(SysInfo::getCurrentModulePath());
+        } catch (const std::exception&) {
+            return _T("Unknown");
+        }
+    }
+
+    TCHAR moduleName[MAX_PATH] = { 'U', 'n', 'k', 'o', 'w', 'n', TCHAR(0) };
+
+    const LPCTSTR format = _T("[%04u/%02u/%02u %02u:%02u:%02u.%03u, %s (PID: %u, TID: %u), %s:%u (%s)]\n\t%s: %s\n");
+
+    enum State { NotInitialized, Initializing, Initialized };
+    State state = NotInitialized;
+}
+
+
+LogEvent::LogEvent() {
+    memset(this, 0, sizeof(*this));
+    moduleName = tstring();
+    logLevel = tstring();
+    fileName = tstring();
+    funcName = tstring();
+    message = tstring();
+}
+
+
+StderrLogAppender::StderrLogAppender() {
+}
+
+
+/*static*/
+Logger& Logger::defaultLogger() {
+    Logger* reply = reinterpret_cast<Logger*>(defaultLoggerMemory);
+
+    if (!reply->appender) {
+        // Memory leak by design. Not an issue at all as this is global
+        // object. OS will do resources clean up anyways when application
+        // terminates and the default log appender should live as long as
+        // application lives.
+        reply->appender = new (defaultLogAppenderMemory) StderrLogAppender();
+    }
+
+    if (Initializing == state) {
+        // Recursive call to Logger::defaultLogger.
+        moduleName[0] = TCHAR(0);
+    } else if (NotInitialized == state) {
+        state = Initializing;
+
+        tstring mname = retrieveModuleName();
+        mname.resize(_countof(moduleName) - 1);
+        std::memcpy(moduleName, mname.c_str(), mname.size());
+        moduleName[mname.size()] = TCHAR(0);
+
+        // if JPACKAGE_DEBUG environment variable is NOT set to "true" disable
+        // logging.
+        if (SysInfo::getEnvVariable(std::nothrow,
+                L"JPACKAGE_DEBUG") != L"true") {
+            reply->appender = &nopLogApender;
+        }
+
+        state = Initialized;
+    }
+
+    return *reply;
+}
+
+Logger::Logger(LogAppender& appender, LogLevel logLevel)
+        : level(logLevel), appender(&appender) {
+}
+
+void Logger::setLogLevel(LogLevel logLevel) {
+    level = logLevel;
+}
+
+Logger::~Logger() {
+}
+
+
+bool Logger::isLoggable(LogLevel logLevel) const {
+    return logLevel >= level;
+}
+
+void Logger::log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
+        LPCTSTR funcName, const tstring& message) const {
+    LogEvent logEvent;
+
+    // [YYYY/MM/DD HH:MM:SS.ms, <module> (PID: processID, TID: threadID),
+    // fileName:lineNum (funcName)] <tab>LEVEL: message
+    GetLocalTime(&logEvent.ts);
+
+    logEvent.pid = GetCurrentProcessId();
+    logEvent.tid = GetCurrentThreadId();
+    logEvent.moduleName = moduleName;
+    logEvent.fileName = FileUtils::basename(fileName);
+    logEvent.funcName = funcName;
+    logEvent.logLevel = getLogLevelStr(logLevel);
+    logEvent.lineNum = lineNum;
+    logEvent.message = message;
+
+    appender->append(logEvent);
+}
+
+
+void StderrLogAppender::append(const LogEvent& v)
+{
+    const tstring out = tstrings::unsafe_format(format,
+        unsigned(v.ts.wYear), unsigned(v.ts.wMonth), unsigned(v.ts.wDay),
+        unsigned(v.ts.wHour), unsigned(v.ts.wMinute), unsigned(v.ts.wSecond),
+                unsigned(v.ts.wMilliseconds),
+        v.moduleName.c_str(), v.pid, v.tid,
+        v.fileName.c_str(), v.lineNum, v.funcName.c_str(),
+        v.logLevel.c_str(),
+        v.message.c_str());
+
+    std::cerr << tstrings::toUtf8(out);
+}
+
+
+// Logger::ScopeTracer
+Logger::ScopeTracer::ScopeTracer(Logger &logger, LogLevel logLevel,
+        LPCTSTR fileName, int lineNum, LPCTSTR funcName,
+        const tstring& scopeName) : log(logger), level(logLevel),
+        file(fileName), line(lineNum),
+        func(funcName), scope(scopeName), needLog(logger.isLoggable(logLevel)) {
+    if (needLog) {
+        log.log(level, file.c_str(), line, func.c_str(),
+                tstrings::any() << "Entering " << scope);
+    }
+}
+
+Logger::ScopeTracer::~ScopeTracer() {
+    if (needLog) {
+        // we don't know what line is end of scope at, so specify line 0
+        // and add note about line when the scope begins
+        log.log(level, file.c_str(), 0, func.c_str(),
+                tstrings::any() << "Exiting " << scope << " (entered at "
+                << FileUtils::basename(file) << ":" << line << ")");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/Log.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef __LOG_H_INCLUDED_
+#define __LOG_H_INCLUDED_
+
+#include <windows.h>
+#include "tstrings.h"
+
+
+/* Default logger (Logger::defaultLogger()) writes log messages to
+ * the default log file.
+ * Common scenario:
+ *   - main() function configures default logger:
+ *       FileLogAppender appender(_T("my_log_filename.log"));
+ *       Logger::defaultLogger().setAppender(appender);
+ *       Logger::defaultLogger().setLogLevel(LOG_INFO);
+ * If the default file name and log level are not set,
+ *  _T("jusched.log")/LOG_TRACE are used.
+ *
+ * Logger fileName specifies only file name,
+ * full path for the log file depends on the platform
+ * (usually value of the TMP env. var)
+ */
+
+struct LogEvent {
+    SYSTEMTIME ts;
+    long tid;
+    long pid;
+    tstring moduleName;
+    tstring logLevel;
+    tstring fileName;
+    int lineNum;
+    tstring funcName;
+    tstring message;
+
+    LogEvent();
+};
+
+
+class LogAppender {
+public:
+    virtual ~LogAppender() {
+    }
+    virtual void append(const LogEvent& v) = 0;
+};
+
+
+class NopLogAppender: public LogAppender {
+public:
+    virtual void append(const LogEvent& v) {};
+};
+
+
+class TeeLogAppender: public LogAppender {
+public:
+    TeeLogAppender(LogAppender* first, LogAppender* second):
+            first(first), second(second) {
+    }
+    virtual ~TeeLogAppender() {
+    }
+    virtual void append(const LogEvent& v) {
+        if (first) {
+            first->append(v);
+        }
+        if (second) {
+            second->append(v);
+        }
+    }
+private:
+    LogAppender* first;
+    LogAppender* second;
+};
+
+
+/**
+ * Writes log events to stderr.
+ */
+class StderrLogAppender: public LogAppender {
+public:
+    explicit StderrLogAppender();
+
+    virtual void append(const LogEvent& v);
+};
+
+
+class Logger {
+public:
+    enum LogLevel {
+        LOG_TRACE,
+        LOG_INFO,
+        LOG_WARNING,
+        LOG_ERROR
+    };
+
+    static Logger& defaultLogger();
+
+    explicit Logger(LogAppender& appender, LogLevel logLevel = LOG_TRACE);
+    ~Logger();
+
+    LogAppender& setAppender(LogAppender& v) {
+        LogAppender& oldAppender = *appender;
+        appender = &v;
+        return oldAppender;
+    }
+
+    LogAppender& getAppender() const {
+        return *appender;
+    }
+
+    void setLogLevel(LogLevel logLevel);
+
+    bool isLoggable(LogLevel logLevel) const ;
+    void log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
+            LPCTSTR funcName, const tstring& message) const;
+    void log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
+            LPCTSTR funcName, const tstrings::any& message) const {
+        return log(logLevel, fileName, lineNum, funcName, message.tstr());
+    }
+    void log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
+            LPCTSTR funcName, tstring::const_pointer message) const {
+        return log(logLevel, fileName, lineNum, funcName, tstring(message));
+    }
+
+    // internal class for scope tracing
+    class ScopeTracer {
+    public:
+        ScopeTracer(Logger &logger, LogLevel logLevel, LPCTSTR fileName,
+                int lineNum, LPCTSTR funcName, const tstring& scopeName);
+        ~ScopeTracer();
+
+    private:
+        const Logger &log;
+        const LogLevel level;
+        const bool needLog;
+        const tstring file;
+        const int line;
+        const tstring func;
+        const tstring scope;
+    };
+
+private:
+    LogLevel level;
+    LogAppender* appender;
+};
+
+
+// base logging macro
+#define LOGGER_LOG(logger, logLevel, message) \
+    do { \
+        if (logger.isLoggable(logLevel)) { \
+            logger.log(logLevel, _T(__FILE__), __LINE__, _T(__FUNCTION__), message); \
+        } \
+    } while(false)
+
+
+// custom logger macros
+#define LOGGER_TRACE(logger, message)   LOGGER_LOG(logger, Logger::LOG_TRACE, message)
+#define LOGGER_INFO(logger, message)    LOGGER_LOG(logger, Logger::LOG_INFO, message)
+#define LOGGER_WARNING(logger, message) LOGGER_LOG(logger, Logger::LOG_WARNING, message)
+#define LOGGER_ERROR(logger, message)   LOGGER_LOG(logger, Logger::LOG_ERROR, message)
+// scope tracing macros
+#define LOGGER_TRACE_SCOPE(logger, scopeName) \
+    Logger::ScopeTracer tracer__COUNTER__(logger, Logger::LOG_TRACE, _T(__FILE__), __LINE__, _T(__FUNCTION__), scopeName)
+#define LOGGER_TRACE_FUNCTION(logger)   LOGGER_TRACE_SCOPE(logger, _T(__FUNCTION__))
+
+
+// default logger macros
+#define LOG_TRACE(message)              LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_TRACE, message)
+#define LOG_INFO(message)               LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_INFO, message)
+#define LOG_WARNING(message)            LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_WARNING, message)
+#define LOG_ERROR(message)              LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_ERROR, message)
+// scope tracing macros
+// logs (_T("Entering ") + scopeName) at the beging, (_T("Exiting ") + scopeName) at the end of scope
+#define LOG_TRACE_SCOPE(scopeName)      LOGGER_TRACE_SCOPE(Logger::defaultLogger(), scopeName)
+// logs (_T("Entering ") + functionName) at the beging, (_T("Exiting ") + __FUNCTION__) at the end of scope
+#define LOG_TRACE_FUNCTION()            LOGGER_TRACE_FUNCTION(Logger::defaultLogger())
+
+
+#endif // __LOG_H_INCLUDED_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/ResourceEditor.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <algorithm>
+#include <fstream>
+#include "ResourceEditor.h"
+#include "WinErrorHandling.h"
+#include "Log.h"
+
+
+ResourceEditor::FileLock::FileLock(const std::wstring& binaryPath) {
+    h = BeginUpdateResource(binaryPath.c_str(), FALSE);
+    if (NULL == h) {
+        JP_THROW(SysError(tstrings::any() << "BeginUpdateResource("
+                    << binaryPath << ") failed", BeginUpdateResource));
+    }
+
+    discard(false);
+}
+
+
+ResourceEditor::FileLock::~FileLock() {
+    if (!EndUpdateResource(h, theDiscard)) {
+        JP_NO_THROW(JP_THROW(SysError(tstrings::any()
+            << "EndUpdateResource(" << h << ") failed.", EndUpdateResource)));
+    }
+}
+
+
+ResourceEditor::ResourceEditor() {
+    language(MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)).type(unsigned(0)).id(unsigned(0));
+}
+
+
+ResourceEditor& ResourceEditor::type(unsigned v) {
+    return type(MAKEINTRESOURCE(v));
+}
+
+
+ResourceEditor& ResourceEditor::type(LPCWSTR v) {
+    if (IS_INTRESOURCE(v)) {
+        std::wostringstream printer;
+        printer << L"#" << reinterpret_cast<size_t>(v);
+        theType = printer.str();
+        theTypePtr = MAKEINTRESOURCE(static_cast<DWORD>(reinterpret_cast<DWORD_PTR>(v)));
+    } else {
+        theType = v;
+        theTypePtr = theType.c_str();
+    }
+    return *this;
+}
+
+
+ResourceEditor& ResourceEditor::id(unsigned v) {
+    return id(MAKEINTRESOURCE(v));
+}
+
+
+ResourceEditor& ResourceEditor::id(LPCWSTR v) {
+    if (IS_INTRESOURCE(v)) {
+        std::wostringstream printer;
+        printer << L"#" << reinterpret_cast<size_t>(v);
+        theId = printer.str();
+    } else {
+        theId = v;
+        theIdPtr = theId.c_str();
+    }
+    return *this;
+}
+
+
+ResourceEditor& ResourceEditor::apply(const FileLock& dstBinary,
+                            std::istream& srcStream, std::streamsize size) {
+
+    typedef std::vector<BYTE> ByteArray;
+    ByteArray buf;
+    if (size <= 0) {
+        // Read the entire stream.
+        buf = ByteArray((std::istreambuf_iterator<char>(srcStream)),
+                                            std::istreambuf_iterator<char>());
+    } else {
+        buf.resize(size_t(size));
+        srcStream.read(reinterpret_cast<char*>(buf.data()), size);
+    }
+
+    auto reply = UpdateResource(dstBinary.get(), theTypePtr, theIdPtr, lang,
+                                buf.data(), static_cast<DWORD>(buf.size()));
+    if (reply == FALSE) {
+        JP_THROW(SysError("UpdateResource() failed", UpdateResource));
+    }
+
+    return *this;
+}
+
+
+ResourceEditor& ResourceEditor::apply(const FileLock& dstBinary,
+                                                const std::wstring& srcFile) {
+    std::ifstream input(srcFile, std::ios_base::binary);
+    input.exceptions(std::ios::failbit | std::ios::badbit);
+    return apply(dstBinary, input);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/ResourceEditor.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef RESOURCEEDITOR_H
+#define RESOURCEEDITOR_H
+
+#include <windows.h>
+#include <vector>
+#include <string>
+
+
+class ResourceEditor {
+public:
+    class FileLock {
+    public:
+        FileLock(const std::wstring& binaryPath);
+        ~FileLock();
+
+        HANDLE get() const {
+            return h;
+        }
+
+        void discard(bool v = true) {
+            theDiscard = v;
+        }
+
+    private:
+        FileLock(const FileLock&);
+        FileLock& operator=(const FileLock&);
+    private:
+        HANDLE h;
+        bool theDiscard;
+    };
+
+public:
+    ResourceEditor();
+
+    /**
+     * Set the language identifier of the resource to be updated.
+     */
+    ResourceEditor& language(unsigned v) {
+        lang = v;
+        return *this;
+    }
+
+    /**
+     * Set the resource type to be updated.
+     */
+    ResourceEditor& type(unsigned v);
+
+    /**
+     * Set the resource type to be updated.
+     */
+    ResourceEditor& type(LPCWSTR v);
+
+    /**
+     * Set resource ID.
+     */
+    ResourceEditor& id(unsigned v);
+
+    /**
+     * Set resource ID.
+     */
+    ResourceEditor& id(LPCWSTR v);
+
+    /**
+     * Relaces resource configured in the given binary with the given data stream.
+     */
+    ResourceEditor& apply(const FileLock& dstBinary, std::istream& srcStream, std::streamsize size=0);
+
+    /**
+     * Relaces resource configured in the given binary with contents of
+     * the given binary file.
+     */
+    ResourceEditor& apply(const FileLock& dstBinary, const std::wstring& srcFile);
+
+private:
+    unsigned lang;
+    std::wstring theId;
+    LPCWSTR theIdPtr;
+    std::wstring theType;
+    LPCWSTR theTypePtr;
+};
+
+#endif // #ifndef RESOURCEEDITOR_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/SourceCodePos.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+
+#ifndef SourceCodePos_h
+#define SourceCodePos_h
+
+
+//
+// Position in source code.
+//
+
+struct SourceCodePos
+{
+    SourceCodePos(const char* fl, const char* fnc, int l):
+                                                file(fl), func(fnc), lno(l)
+    {
+    }
+
+    const char* file;
+    const char* func;
+    int lno;
+};
+
+
+// Initializes SourceCodePos instance with the
+// information from the point of calling.
+#define JP_SOURCE_CODE_POS SourceCodePos(__FILE__, __FUNCTION__, __LINE__)
+
+
+#endif // #ifndef SourceCodePos_h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/SysInfo.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+
+#ifndef SYSINFO_H
+#define SYSINFO_H
+
+#include "tstrings.h"
+
+
+//
+// This namespace provides information about environment in which
+// the current application runs.
+// It is for general purpose use.
+// Functions in this namespaces are just queries about the environment.
+// Functions that change the existing environment like file or directory
+// creation should not be added to this namespace.
+//
+namespace SysInfo {
+    /**
+     * Returns temp dir (for the current user).
+     */
+    tstring getTempDir();
+
+    /**
+     * Returns absolute path to the process executable.
+     */
+    tstring getProcessModulePath();
+
+    /**
+     * Returns absolute path to the current executable module.
+     */
+    tstring getCurrentModulePath();
+
+    enum CommandArgProgramNameMode {
+        IncludeProgramName,
+        ExcludeProgramName
+    };
+    /**
+     * Retrieves the command-line arguments for the current process.
+     * With IncludeProgramName option returns result similar to argv/argc.
+     * With ExcludeProgramName option program name
+     *  (the 1st element of command line)
+     * is excluded.
+     */
+    tstring_array getCommandArgs(
+            CommandArgProgramNameMode progNameMode = ExcludeProgramName);
+
+    /**
+     * Returns value of environment variable with the given name.
+     * Throws exception if variable is not set or any other error occurred
+     * reading the value.
+     */
+    tstring getEnvVariable(const tstring& name);
+
+    /**
+     * Returns value of environment variable with the given name.
+     * Returns value of 'defValue' parameter if variable is not set or any
+     * other error occurred reading the value.
+     */
+    tstring getEnvVariable(const std::nothrow_t&, const tstring& name,
+            const tstring& defValue=tstring());
+
+    /**
+     * Returns 'true' if environment variable with the given name is set.
+     */
+    bool isEnvVariableSet(const tstring& name);
+}
+
+#endif // SYSINFO_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/UniqueHandle.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef UNIQUEHANDLE_H
+#define UNIQUEHANDLE_H
+
+#include <windows.h>
+#include <memory>
+
+
+struct WndHandleDeleter {
+    typedef HANDLE pointer;
+
+    void operator()(HANDLE h) {
+        ::CloseHandle(h);
+    }
+};
+
+typedef std::unique_ptr<HANDLE, WndHandleDeleter> UniqueHandle;
+
+#endif // #ifndef UNIQUEHANDLE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/Utils.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include "Windows.h"
+#include "Utils.h"
+
+#define BUFFER_SIZE 4096
+
+wstring GetStringFromJString(JNIEnv *pEnv, jstring jstr) {
+    const jchar *pJChars = pEnv->GetStringChars(jstr, NULL);
+    if (pJChars == NULL) {
+        return wstring(L"");
+    }
+
+    wstring wstr(pJChars);
+
+    pEnv->ReleaseStringChars(jstr, pJChars);
+
+    return wstr;
+}
+
+jstring GetJStringFromString(JNIEnv *pEnv,
+            const jchar *unicodeChars, jsize len) {
+    return pEnv->NewString(unicodeChars, len);
+}
+
+wstring GetLongPath(wstring path) {
+    wstring result(L"");
+
+    size_t len = path.length();
+    if (len > 1) {
+        if (path.at(len - 1) == '\\') {
+            path.erase(len - 1);
+        }
+    }
+
+    TCHAR *pBuffer = new TCHAR[BUFFER_SIZE];
+    if (pBuffer != NULL) {
+        DWORD dwResult = GetLongPathName(path.c_str(), pBuffer, BUFFER_SIZE);
+        if (dwResult > 0 && dwResult < BUFFER_SIZE) {
+            result = wstring(pBuffer);
+        } else {
+            delete [] pBuffer;
+            pBuffer = new TCHAR[dwResult];
+            if (pBuffer != NULL) {
+                DWORD dwResult2 =
+                        GetLongPathName(path.c_str(), pBuffer, dwResult);
+                if (dwResult2 == (dwResult - 1)) {
+                    result = wstring(pBuffer);
+                }
+            }
+        }
+
+        if (pBuffer != NULL) {
+            delete [] pBuffer;
+        }
+    }
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/Utils.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <string>
+#include "jni.h"
+
+using namespace std;
+
+wstring GetStringFromJString(JNIEnv *pEnv, jstring jstr);
+jstring GetJStringFromString(JNIEnv *pEnv, const jchar *unicodeChars,
+        jsize len);
+
+wstring GetLongPath(wstring path);
+
+#endif // UTILS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/VersionInfoSwap.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2015, 2019, 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.
+ */
+
+#include "VersionInfoSwap.h"
+
+#include <stdio.h>
+#include <tchar.h>
+
+#include <windows.h>
+#include <stdio.h>
+#include <Strsafe.h>
+#include <fstream>
+#include <locale>
+#include <codecvt>
+
+using namespace std;
+
+/*
+ * [Property file] contains key/value pairs
+ * The swap tool uses these pairs to create new version resource
+ *
+ * See MSDN docs for VS_VERSIONINFO structure that
+ * depicts organization of data in this version resource
+ *    https://msdn.microsoft.com/en-us/library/ms647001(v=vs.85).aspx
+ *
+ * The swap tool makes changes in [Executable file]
+ * The tool assumes that the executable file has no version resource
+ * and it adds new resource in the executable file.
+ * If the executable file has an existing version resource, then
+ * the existing version resource will be replaced with new one.
+ */
+
+VersionInfoSwap::VersionInfoSwap(wstring executableProperties,
+        wstring launcher) {
+    m_executableProperties = executableProperties;
+    m_launcher = launcher;
+}
+
+bool VersionInfoSwap::PatchExecutable() {
+    bool b = LoadFromPropertyFile();
+    if (!b) {
+        return false;
+    }
+
+    ByteBuffer buf;
+    b = CreateNewResource(&buf);
+    if (!b) {
+        return false;
+    }
+
+    b = this->UpdateResource(buf.getPtr(), static_cast<DWORD> (buf.getPos()));
+    if (!b) {
+        return false;
+    }
+
+    return true;
+}
+
+bool VersionInfoSwap::LoadFromPropertyFile() {
+    wifstream stream(m_executableProperties.c_str());
+
+    const locale empty_locale = locale::empty();
+    const locale utf8_locale =
+            locale(empty_locale, new codecvt_utf8<wchar_t>());
+    stream.imbue(utf8_locale);
+
+    if (stream.is_open() == true) {
+        int lineNumber = 1;
+        while (stream.eof() == false) {
+            wstring line;
+            getline(stream, line);
+
+            // # at the first character will comment out the line.
+            if (line.empty() == false && line[0] != '#') {
+                wstring::size_type pos = line.find('=');
+                if (pos != wstring::npos) {
+                    wstring name = line.substr(0, pos);
+                    wstring value = line.substr(pos + 1);
+                    m_props[name] = value;
+                }
+            }
+            lineNumber++;
+        }
+        return true;
+    }
+
+    return false;
+}
+
+/*
+ * Creates new version resource
+ *
+ * MSND docs for VS_VERSION_INFO structure
+ *     https://msdn.microsoft.com/en-us/library/ms647001(v=vs.85).aspx
+ */
+bool VersionInfoSwap::CreateNewResource(ByteBuffer *buf) {
+    size_t versionInfoStart = buf->getPos();
+    buf->AppendWORD(0);
+    buf->AppendWORD(sizeof VS_FIXEDFILEINFO);
+    buf->AppendWORD(0);
+    buf->AppendString(TEXT("VS_VERSION_INFO"));
+    buf->Align(4);
+
+    VS_FIXEDFILEINFO fxi;
+    if (!FillFixedFileInfo(&fxi)) {
+        return false;
+    }
+    buf->AppendBytes((BYTE*) & fxi, sizeof (VS_FIXEDFILEINFO));
+    buf->Align(4);
+
+    // String File Info
+    size_t stringFileInfoStart = buf->getPos();
+    buf->AppendWORD(0);
+    buf->AppendWORD(0);
+    buf->AppendWORD(1);
+    buf->AppendString(TEXT("StringFileInfo"));
+    buf->Align(4);
+
+    // String Table
+    size_t stringTableStart = buf->getPos();
+    buf->AppendWORD(0);
+    buf->AppendWORD(0);
+    buf->AppendWORD(1);
+
+    // "040904B0" = LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP
+    buf->AppendString(TEXT("040904B0"));
+    buf->Align(4);
+
+    // Strings
+    vector<wstring> keys;
+    for (map<wstring, wstring>::const_iterator it =
+            m_props.begin(); it != m_props.end(); ++it) {
+        keys.push_back(it->first);
+    }
+
+    for (size_t index = 0; index < keys.size(); index++) {
+        wstring name = keys[index];
+        wstring value = m_props[name];
+
+        size_t stringStart = buf->getPos();
+        buf->AppendWORD(0);
+        buf->AppendWORD(static_cast<WORD> (value.length()));
+        buf->AppendWORD(1);
+        buf->AppendString(name);
+        buf->Align(4);
+        buf->AppendString(value);
+        buf->ReplaceWORD(stringStart,
+                static_cast<WORD> (buf->getPos() - stringStart));
+        buf->Align(4);
+    }
+
+    buf->ReplaceWORD(stringTableStart,
+            static_cast<WORD> (buf->getPos() - stringTableStart));
+    buf->ReplaceWORD(stringFileInfoStart,
+            static_cast<WORD> (buf->getPos() - stringFileInfoStart));
+
+    // VarFileInfo
+    size_t varFileInfoStart = buf->getPos();
+    buf->AppendWORD(1);
+    buf->AppendWORD(0);
+    buf->AppendWORD(1);
+    buf->AppendString(TEXT("VarFileInfo"));
+    buf->Align(4);
+
+    buf->AppendWORD(0x24);
+    buf->AppendWORD(0x04);
+    buf->AppendWORD(0x00);
+    buf->AppendString(TEXT("Translation"));
+    buf->Align(4);
+    // "000004B0" = LANG_NEUTRAL/SUBLANG_ENGLISH_US, Unicode CP
+    buf->AppendWORD(0x0000);
+    buf->AppendWORD(0x04B0);
+
+    buf->ReplaceWORD(varFileInfoStart,
+            static_cast<WORD> (buf->getPos() - varFileInfoStart));
+    buf->ReplaceWORD(versionInfoStart,
+            static_cast<WORD> (buf->getPos() - versionInfoStart));
+
+    return true;
+}
+
+bool VersionInfoSwap::FillFixedFileInfo(VS_FIXEDFILEINFO *fxi) {
+    wstring fileVersion;
+    wstring productVersion;
+    int ret;
+
+    fileVersion = m_props[TEXT("FileVersion")];
+    productVersion = m_props[TEXT("ProductVersion")];
+
+    unsigned fv_1 = 0, fv_2 = 0, fv_3 = 0, fv_4 = 0;
+    unsigned pv_1 = 0, pv_2 = 0, pv_3 = 0, pv_4 = 0;
+
+    ret = _stscanf_s(fileVersion.c_str(),
+            TEXT("%d.%d.%d.%d"), &fv_1, &fv_2, &fv_3, &fv_4);
+    if (ret <= 0 || ret > 4) {
+        return false;
+    }
+
+    ret = _stscanf_s(productVersion.c_str(),
+            TEXT("%d.%d.%d.%d"), &pv_1, &pv_2, &pv_3, &pv_4);
+    if (ret <= 0 || ret > 4) {
+        return false;
+    }
+
+    fxi->dwSignature = 0xFEEF04BD;
+    fxi->dwStrucVersion = 0x00010000;
+
+    fxi->dwFileVersionMS = MAKELONG(fv_2, fv_1);
+    fxi->dwFileVersionLS = MAKELONG(fv_4, fv_3);
+    fxi->dwProductVersionMS = MAKELONG(pv_2, pv_1);
+    fxi->dwProductVersionLS = MAKELONG(pv_4, pv_3);
+
+    fxi->dwFileFlagsMask = 0;
+    fxi->dwFileFlags = 0;
+    fxi->dwFileOS = VOS_NT_WINDOWS32;
+
+    wstring exeExt =
+            m_launcher.substr(m_launcher.find_last_of(TEXT(".")));
+    if (exeExt == TEXT(".exe")) {
+        fxi->dwFileType = VFT_APP;
+    } else if (exeExt == TEXT(".dll")) {
+        fxi->dwFileType = VFT_DLL;
+    } else {
+        fxi->dwFileType = VFT_UNKNOWN;
+    }
+    fxi->dwFileSubtype = 0;
+
+    fxi->dwFileDateLS = 0;
+    fxi->dwFileDateMS = 0;
+
+    return true;
+}
+
+/*
+ * Adds new resource in the executable
+ */
+bool VersionInfoSwap::UpdateResource(LPVOID lpResLock, DWORD size) {
+
+    HANDLE hUpdateRes;
+    BOOL r;
+
+    hUpdateRes = ::BeginUpdateResource(m_launcher.c_str(), FALSE);
+    if (hUpdateRes == NULL) {
+        return false;
+    }
+
+    r = ::UpdateResource(hUpdateRes,
+            RT_VERSION,
+            MAKEINTRESOURCE(VS_VERSION_INFO),
+            MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
+            lpResLock,
+            size);
+
+    if (!r) {
+        return false;
+    }
+
+    if (!::EndUpdateResource(hUpdateRes, FALSE)) {
+        return false;
+    }
+
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/VersionInfoSwap.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, 2019, 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.
+ */
+
+#ifndef VERSIONINFOSWAP_H
+#define VERSIONINFOSWAP_H
+
+#include "ByteBuffer.h"
+#include <map>
+
+using namespace std;
+
+class VersionInfoSwap {
+public:
+    VersionInfoSwap(wstring executableProperties, wstring launcher);
+
+    bool PatchExecutable();
+
+private:
+    wstring m_executableProperties;
+    wstring m_launcher;
+
+    map<wstring, wstring> m_props;
+
+    bool LoadFromPropertyFile();
+    bool CreateNewResource(ByteBuffer *buf);
+    bool UpdateResource(LPVOID lpResLock, DWORD size);
+    bool FillFixedFileInfo(VS_FIXEDFILEINFO *fxi);
+};
+
+#endif // VERSIONINFOSWAP_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/WinErrorHandling.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include "WinErrorHandling.h"
+#include "Log.h"
+#include "SysInfo.h"
+#include "FileUtils.h"
+
+
+namespace {
+
+std::string makeMessage(const std::string& msg, const char* label,
+                                            const void* c, DWORD errorCode) {
+    std::ostringstream err;
+    err << (label ? label : "Some error") << " [" << errorCode << "]";
+
+    HMODULE hmodule = NULL;
+    if (c) {
+        GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+                | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+                reinterpret_cast<LPCTSTR>(c), &hmodule);
+
+        if (!hmodule) {
+            LOG_WARNING(tstrings::any() << "GetModuleHandleEx() failed for "
+                    << c << " address.");
+        }
+    }
+    if (hmodule || !c) {
+        err << "(" << SysError::getSysErrorMessage(errorCode, hmodule) << ")";
+    }
+
+    return joinErrorMessages(msg, err.str());
+}
+
+
+std::wstring getSystemMessageDescription(DWORD messageId, HMODULE moduleHandle) {
+    LPWSTR pMsg = NULL;
+    std::wstring descr;
+
+    // we always retrieve UNICODE description from system,
+    // convert it to utf8 if UNICODE is not defined
+
+    while (true) {
+        DWORD res = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
+                | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS
+                | (moduleHandle != NULL ? FORMAT_MESSAGE_FROM_HMODULE : 0),
+                moduleHandle, messageId, 0, (LPWSTR)&pMsg, 0, NULL);
+        if (res > 0) {
+            // replace all non-printed chars with space
+            for (DWORD i=0; i<res; i++) {
+                if (pMsg[i] < L' ') {
+                    pMsg[i] = L' ';
+                }
+            }
+            // trim right (spaces and dots)
+            for (DWORD i=res; i>0; i--) {
+                if (pMsg[i] > L' ' && pMsg[i] != L'.') {
+                    break;
+                }
+                pMsg[i] = 0;
+            }
+
+            descr = pMsg;
+
+            LocalFree(pMsg);
+        } else {
+            // if we fail to get description for specific moduleHandle,
+            // try to get "common" description.
+            if (moduleHandle != NULL) {
+                moduleHandle = NULL;
+                continue;
+            }
+            descr = L"No description available";
+        }
+        break;
+    }
+
+    return descr;
+}
+
+} // namespace
+
+
+SysError::SysError(const tstrings::any& msg, const void* caller, DWORD ec,
+        const char* label):
+
+std::runtime_error(makeMessage(msg.str(), label, caller, ec)) {
+}
+
+std::wstring SysError::getSysErrorMessage(DWORD errCode, HMODULE moduleHandle) {
+    tstrings::any msg;
+    msg << "system error " << errCode
+        << " (" << getSystemMessageDescription(errCode, moduleHandle) << ")";
+    return msg.tstr();
+}
+
+std::wstring SysError::getComErrorMessage(HRESULT hr) {
+    HRESULT hrOrig = hr;
+    // for FACILITY_WIN32 facility we need to reset hiword
+    if(HRESULT_FACILITY(hr) == FACILITY_WIN32) {
+        hr = HRESULT_CODE(hr);
+    }
+    return tstrings::format(_T("COM error 0x%08X (%s)"), hrOrig,
+            getSystemMessageDescription(hr, NULL));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/WinErrorHandling.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+
+#ifndef WinErrorHandling_h
+#define WinErrorHandling_h
+
+
+#include "ErrorHandling.h"
+
+
+class SysError : public std::runtime_error {
+public:
+    SysError(const tstrings::any& msg, const void* caller,
+            DWORD errorCode=GetLastError(), const char* label="System error");
+
+    // returns string "system error <errCode> (error_description)"
+    // in UNICODE is not defined, the string returned is utf8-encoded
+    static std::wstring getSysErrorMessage(DWORD errCode = GetLastError(),
+            HMODULE moduleHandle = NULL);
+
+    // returns string "COM error 0x<hr> (error_description)"
+    // in UNICODE is not defined, the string returned is utf8-encoded
+    static std::wstring getComErrorMessage(HRESULT hr);
+};
+
+#endif // #ifndef WinErrorHandling_h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/WinSysInfo.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <windows.h>
+#include <shellapi.h>
+
+#include "WinSysInfo.h"
+#include "FileUtils.h"
+#include "WinErrorHandling.h"
+
+#pragma comment(lib, "Shell32")
+
+namespace SysInfo {
+
+tstring getTempDir() {
+    std::vector<TCHAR> buffer(MAX_PATH);
+    DWORD res = GetTempPath(static_cast<DWORD>(buffer.size()), buffer.data());
+    if (res > buffer.size()) {
+        buffer.resize(res);
+        GetTempPath(static_cast<DWORD>(buffer.size()), buffer.data());
+    }
+    return FileUtils::removeTrailingSlash(buffer.data());
+}
+
+namespace {
+
+template <class Func>
+tstring getSystemDirImpl(Func func, const std::string& label) {
+    std::vector<TCHAR> buffer(MAX_PATH);
+    for (int i=0; i<2; i++) {
+        DWORD res = func(buffer.data(), static_cast<DWORD>(buffer.size()));
+        if (!res) {
+            JP_THROW(SysError(label + " failed", func));
+        }
+        if (res < buffer.size()) {
+            return FileUtils::removeTrailingSlash(buffer.data());
+        }
+        buffer.resize(res + 1);
+    }
+    JP_THROW("Unexpected reply from" + label);
+}
+
+} // namespace
+
+tstring getSystem32Dir() {
+    return getSystemDirImpl(GetSystemDirectory, "GetSystemDirectory");
+}
+
+tstring getWIPath() {
+    return FileUtils::mkpath() << getSystem32Dir() << _T("msiexec.exe");
+}
+
+namespace {
+
+tstring getModulePath(HMODULE h)
+{
+    std::vector<TCHAR> buf(MAX_PATH);
+    DWORD len = 0;
+    while (true) {
+        len = GetModuleFileName(h, buf.data(), (DWORD)buf.size());
+        if (len < buf.size()) {
+            break;
+        }
+        // buffer is too small, increase it
+        buf.resize(buf.size() * 2);
+    }
+
+    if (len == 0) {
+        // error occured
+        JP_THROW(SysError("GetModuleFileName failed", GetModuleFileName));
+    }
+    return tstring(buf.begin(), buf.begin() + len);
+}
+
+} // namespace
+
+tstring getProcessModulePath() {
+    return getModulePath(NULL);
+}
+
+HMODULE getCurrentModuleHandle()
+{
+    // get module handle for the address of this function
+    LPCWSTR address = reinterpret_cast<LPCWSTR>(getCurrentModuleHandle);
+    HMODULE hmodule = NULL;
+    if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+            | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, address, &hmodule))
+    {
+        JP_THROW(SysError(tstrings::any() << "GetModuleHandleExW failed",
+                GetModuleHandleExW));
+    }
+    return hmodule;
+}
+
+tstring getCurrentModulePath()
+{
+    return getModulePath(getCurrentModuleHandle());
+}
+
+tstring_array getCommandArgs(CommandArgProgramNameMode progNameMode)
+{
+    int argc = 0;
+    tstring_array result;
+
+    LPWSTR *parsedArgs = CommandLineToArgvW(GetCommandLineW(), &argc);
+    if (parsedArgs == NULL) {
+        JP_THROW(SysError("CommandLineToArgvW failed", CommandLineToArgvW));
+    }
+    // the 1st element contains program name
+    for (int i = progNameMode == ExcludeProgramName ? 1 : 0; i < argc; i++) {
+        result.push_back(parsedArgs[i]);
+    }
+    LocalFree(parsedArgs);
+
+    return result;
+}
+
+namespace {
+
+tstring getEnvVariableImpl(const tstring& name, bool* errorOccured=0) {
+    std::vector<TCHAR> buf(10);
+    SetLastError(ERROR_SUCCESS);
+    const DWORD size = GetEnvironmentVariable(name.c_str(), buf.data(),
+                                                            DWORD(buf.size()));
+    if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
+        if (errorOccured) {
+            *errorOccured = true;
+            return tstring();
+        }
+        JP_THROW(SysError(tstrings::any() << "GetEnvironmentVariable("
+            << name << ") failed. Variable not set", GetEnvironmentVariable));
+    }
+
+    if (size > buf.size()) {
+        buf.resize(size);
+        GetEnvironmentVariable(name.c_str(), buf.data(), DWORD(buf.size()));
+        if (GetLastError() != ERROR_SUCCESS) {
+            if (errorOccured) {
+                *errorOccured = true;
+                return tstring();
+            }
+            JP_THROW(SysError(tstrings::any() << "GetEnvironmentVariable("
+                            << name << ") failed", GetEnvironmentVariable));
+        }
+    }
+
+    if (errorOccured) {
+        *errorOccured = false;
+    }
+    return tstring(buf.data());
+}
+
+} // namespace
+
+tstring getEnvVariable(const tstring& name) {
+    return getEnvVariableImpl(name);
+}
+
+tstring getEnvVariable(const std::nothrow_t&, const tstring& name,
+                                                    const tstring& defValue) {
+    bool errorOccured = false;
+    const tstring reply = getEnvVariableImpl(name, &errorOccured);
+    if (errorOccured) {
+        return defValue;
+    }
+    return reply;
+}
+
+bool isEnvVariableSet(const tstring& name) {
+    TCHAR unused[1];
+    SetLastError(ERROR_SUCCESS);
+    GetEnvironmentVariable(name.c_str(), unused, _countof(unused));
+    return GetLastError() != ERROR_ENVVAR_NOT_FOUND;
+}
+
+} // end of namespace SysInfo
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/WinSysInfo.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+
+#ifndef WINSYSINFO_H
+#define WINSYSINFO_H
+
+#include "SysInfo.h"
+
+
+//
+// Windows specific SysInfo.
+//
+namespace SysInfo {
+    // gets Windows System folder. A typical path is C:\Windows\System32.
+    tstring getSystem32Dir();
+
+    // returns full path to msiexec.exe executable
+    tstring getWIPath();
+
+    // Returns handle of the current module (exe or dll).
+    // The function assumes this code is statically linked to the module.
+    HMODULE getCurrentModuleHandle();
+}
+
+
+#endif // WINSYSINFO_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/WindowsRegistry.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <Windows.h>
+#include <strsafe.h>
+#include <tchar.h>
+#include <jni.h>
+
+#include "Utils.h"
+
+// Max value name size per MSDN plus NULL
+#define VALUE_NAME_SIZE 16384
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef jdk_incubator_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE
+#define jdk_incubator_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE 1L
+
+    /*
+     * Class:     jdk_incubator_jpackage_internal_WindowsRegistry
+     * Method:    readDwordValue
+     * Signature: (ILjava/lang/String;Ljava/lang/String;I)I
+     */
+    JNIEXPORT jint JNICALL
+            Java_jdk_incubator_jpackage_internal_WindowsRegistry_readDwordValue(
+            JNIEnv *pEnv, jclass c, jint key, jstring jSubKey,
+            jstring jValue, jint defaultValue) {
+        jint jResult = defaultValue;
+
+        if (key != jdk_incubator_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE) {
+            return jResult;
+        }
+
+        wstring subKey = GetStringFromJString(pEnv, jSubKey);
+        wstring value = GetStringFromJString(pEnv, jValue);
+
+        HKEY hSubKey = NULL;
+        LSTATUS status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey.c_str(), 0,
+                KEY_QUERY_VALUE, &hSubKey);
+        if (status == ERROR_SUCCESS) {
+            DWORD dwValue = 0;
+            DWORD cbData = sizeof (DWORD);
+            status = RegQueryValueEx(hSubKey, value.c_str(), NULL, NULL,
+                    (LPBYTE) & dwValue, &cbData);
+            if (status == ERROR_SUCCESS) {
+                jResult = (jint) dwValue;
+            }
+
+            RegCloseKey(hSubKey);
+        }
+
+        return jResult;
+    }
+
+    /*
+     * Class:     jdk_incubator_jpackage_internal_WindowsRegistry
+     * Method:    openRegistryKey
+     * Signature: (ILjava/lang/String;)J
+     */
+    JNIEXPORT jlong JNICALL
+            Java_jdk_incubator_jpackage_internal_WindowsRegistry_openRegistryKey(
+            JNIEnv *pEnv, jclass c, jint key, jstring jSubKey) {
+        if (key != jdk_incubator_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE) {
+            return 0;
+        }
+
+        wstring subKey = GetStringFromJString(pEnv, jSubKey);
+        HKEY hSubKey = NULL;
+        LSTATUS status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey.c_str(), 0,
+                KEY_QUERY_VALUE, &hSubKey);
+        if (status == ERROR_SUCCESS) {
+            return (jlong)hSubKey;
+        }
+
+        return 0;
+    }
+
+    /*
+     * Class:     jdk_incubator_jpackage_internal_WindowsRegistry
+     * Method:    enumRegistryValue
+     * Signature: (JI)Ljava/lang/String;
+     */
+    JNIEXPORT jstring JNICALL
+            Java_jdk_incubator_jpackage_internal_WindowsRegistry_enumRegistryValue(
+            JNIEnv *pEnv, jclass c, jlong lKey, jint jIndex) {
+        HKEY hKey = (HKEY)lKey;
+        TCHAR valueName[VALUE_NAME_SIZE] = {0}; // Max size per MSDN plus NULL
+        DWORD cchValueName = VALUE_NAME_SIZE;
+        LSTATUS status = RegEnumValue(hKey, (DWORD)jIndex, valueName,
+                &cchValueName, NULL, NULL, NULL, NULL);
+        if (status == ERROR_SUCCESS) {
+            size_t chLength = 0;
+            if (StringCchLength(valueName, VALUE_NAME_SIZE, &chLength)
+                    == S_OK) {
+                return GetJStringFromString(pEnv, valueName, (jsize)chLength);
+            }
+        }
+
+        return NULL;
+    }
+
+    /*
+     * Class:     jdk_incubator_jpackage_internal_WindowsRegistry
+     * Method:    closeRegistryKey
+     * Signature: (J)V
+     */
+    JNIEXPORT void JNICALL
+            Java_jdk_incubator_jpackage_internal_WindowsRegistry_closeRegistryKey(
+            JNIEnv *pEnc, jclass c, jlong lKey) {
+        HKEY hKey = (HKEY)lKey;
+        RegCloseKey(hKey);
+    }
+
+    /*
+     * Class:     jdk_incubator_jpackage_internal_WindowsRegistry
+     * Method:    comparePaths
+     * Signature: (Ljava/lang/String;Ljava/lang/String;)Z
+     */
+     JNIEXPORT jboolean JNICALL
+            Java_jdk_incubator_jpackage_internal_WindowsRegistry_comparePaths(
+            JNIEnv *pEnv, jclass c, jstring jPath1, jstring jPath2) {
+         wstring path1 = GetStringFromJString(pEnv, jPath1);
+         wstring path2 = GetStringFromJString(pEnv, jPath2);
+
+         path1 = GetLongPath(path1);
+         path2 = GetLongPath(path2);
+
+         if (path1.length() == 0 || path2.length() == 0) {
+             return JNI_FALSE;
+         }
+
+         if (path1.length() != path2.length()) {
+             return JNI_FALSE;
+         }
+
+         if (_tcsnicmp(path1.c_str(), path2.c_str(), path1.length()) == 0) {
+             return JNI_TRUE;
+         }
+
+         return JNI_FALSE;
+     }
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/jpackage.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2011, 2019, 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <windows.h>
+
+#include "ResourceEditor.h"
+#include "WinErrorHandling.h"
+#include "IconSwap.h"
+#include "VersionInfoSwap.h"
+#include "Utils.h"
+
+using namespace std;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /*
+     * Class:     jdk_incubator_jpackage_internal_WindowsAppImageBuilder
+     * Method:    iconSwap
+     * Signature: (Ljava/lang/String;Ljava/lang/String;)I
+     */
+    JNIEXPORT jint JNICALL
+            Java_jdk_incubator_jpackage_internal_WindowsAppImageBuilder_iconSwap(
+            JNIEnv *pEnv, jclass c, jstring jIconTarget, jstring jLauncher) {
+        wstring iconTarget = GetStringFromJString(pEnv, jIconTarget);
+        wstring launcher = GetStringFromJString(pEnv, jLauncher);
+
+        if (ChangeIcon(iconTarget, launcher)) {
+            return 0;
+        }
+
+        return 1;
+    }
+
+    /*
+     * Class:     jdk_incubator_jpackage_internal_WindowsAppImageBuilder
+     * Method:    versionSwap
+     * Signature: (Ljava/lang/String;Ljava/lang/String;)I
+     */
+    JNIEXPORT jint JNICALL
+            Java_jdk_incubator_jpackage_internal_WindowsAppImageBuilder_versionSwap(
+            JNIEnv *pEnv, jclass c, jstring jExecutableProperties,
+            jstring jLauncher) {
+
+        wstring executableProperties = GetStringFromJString(pEnv,
+                jExecutableProperties);
+        wstring launcher = GetStringFromJString(pEnv, jLauncher);
+
+        VersionInfoSwap vs(executableProperties, launcher);
+        if (vs.PatchExecutable()) {
+            return 0;
+        }
+
+        return 1;
+    }
+
+    /*
+     * Class:     jdk_incubator_jpackage_internal_WinExeBundler
+     * Method:    embedMSI
+     * Signature: (Ljava/lang/String;Ljava/lang/String;)I
+     */
+    JNIEXPORT jint JNICALL Java_jdk_incubator_jpackage_internal_WinExeBundler_embedMSI(
+            JNIEnv *pEnv, jclass c, jstring jexePath, jstring jmsiPath) {
+
+        const wstring exePath = GetStringFromJString(pEnv, jexePath);
+        const wstring msiPath = GetStringFromJString(pEnv, jmsiPath);
+
+        JP_TRY;
+
+        ResourceEditor()
+            .id(L"msi")
+            .type(RT_RCDATA)
+            .apply(ResourceEditor::FileLock(exePath), msiPath);
+
+        return 0;
+
+        JP_CATCH_ALL;
+
+        return 1;
+    }
+
+    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
+            LPVOID lpvReserved) {
+        return TRUE;
+    }
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/tstrings.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdexcept>
+#include <algorithm>
+
+#include "tstrings.h"
+#include "ErrorHandling.h"
+
+
+namespace tstrings {
+
+/* Create formatted string
+ */
+tstring unsafe_format(tstring::const_pointer format, ...) {
+    if (!format) {
+        throw std::invalid_argument("Destination buffer can't be NULL");
+    }
+
+    tstring fmtout;
+    int ret;
+    const int inc = 256;
+
+    va_list args;
+    va_start(args, format);
+    do {
+        fmtout.resize(fmtout.size() + inc);
+#ifdef _MSC_VER
+        ret = _vsntprintf_s(&*fmtout.begin(), fmtout.size(), _TRUNCATE, format, args);
+#else
+        // With g++ this compiles only with '-std=gnu++0x' option
+        ret = vsnprintf(&*fmtout.begin(), fmtout.size(), format, args);
+#endif
+    } while(-1 == ret);
+    va_end(args);
+
+    //update string size by actual value
+    fmtout.resize(ret);
+
+    return fmtout;
+}
+
+/*
+ * Tests if two strings are equal according to CompareType.
+ *
+ * a - string to compare
+ * b - string to compare
+ * ct - CASE_SENSITIVE: case sensitive comparing type
+ *      IGNORE_CASE: case insensitive comparing type
+ */
+bool equals(const tstring& a, const tstring& b, const CompareType ct) {
+    if (IGNORE_CASE==ct) {
+        return toLower(a) == toLower(b);
+    }
+    return a == b;
+}
+
+bool startsWith(const tstring &str, const tstring &substr, const CompareType ct)
+{
+    if (str.size() < substr.size()) {
+        return false;
+    }
+    const tstring startOfStr = str.substr(0, substr.size());
+    return tstrings::equals(startOfStr, substr, ct);
+}
+
+bool endsWith(const tstring &str, const tstring &substr, const CompareType ct)
+{
+    if (str.size() < substr.size()) {
+        return false;
+    }
+    const tstring endOfStr = str.substr(str.size() - substr.size());
+    return tstrings::equals(endOfStr, substr, ct);
+}
+
+/*
+ * Split string into a vector with given delimiter string
+ *
+ * strVector - string vector to store split tstring
+ * str - string to split
+ * delimiter - delimiter to split the string around
+ * st - ST_ALL: return value includes an empty string
+ *      ST_EXCEPT_EMPTY_STRING: return value does not include an empty string
+ *
+ * Note: It does not support multiple delimiters
+ */
+void split(tstring_array &strVector, const tstring &str,
+          const tstring &delimiter, const SplitType st) {
+    tstring::size_type start = 0, end = 0, length = str.length();
+
+    if (length == 0 || delimiter.length() == 0) {
+        return;
+    }
+
+    end = str.find(delimiter, start);
+    while(end != tstring::npos) {
+        if(st == ST_ALL || end - start > 1 ) {
+            strVector.push_back(str.substr(start, end == tstring::npos ?
+                                                  tstring::npos : end - start));
+        }
+        start = end > (tstring::npos - delimiter.size()) ?
+                tstring::npos : end + delimiter.size();
+        end = str.find(delimiter, start);
+    }
+
+    if(st == ST_ALL || start < length) {
+        strVector.push_back(str.substr(start, length - start));
+    }
+}
+
+/*
+ * Convert uppercase letters to lowercase
+ */
+tstring toLower(const tstring& str) {
+    tstring lower(str);
+    tstring::iterator ok = std::transform(lower.begin(), lower.end(),
+                                          lower.begin(), tolower);
+    if (ok!=lower.end()) {
+        lower.resize(0);
+    }
+    return lower;
+}
+
+
+/*
+ * Replace all substring occurrences in a tstring.
+ * If 'str' or 'search' is empty the function returns 'str'.
+ * The given 'str' remains unchanged in any case.
+ * The function returns changed copy of 'str'.
+ */
+tstring replace(const tstring &str, const tstring &search, const tstring &replace)
+{
+    if (search.empty()) {
+        return str;
+    }
+
+    tstring s(str);
+
+    for (size_t pos = 0; ; pos += replace.length()) {
+        pos = s.find(search, pos);
+        if (pos == tstring::npos) {
+            break;
+        }
+        s.erase(pos, search.length());
+        s.insert(pos, replace);
+    }
+    return s;
+}
+
+
+/*
+ * Remove trailing spaces
+ */
+
+tstring trim(const tstring& str, const tstring& whitespace) {
+    const size_t strBegin = str.find_first_not_of(whitespace);
+    if (strBegin == std::string::npos) {
+        return tstring(); // no content
+    }
+
+    const size_t  strEnd = str.find_last_not_of(whitespace);
+    const size_t strRange = strEnd - strBegin + 1;
+
+    return str.substr(strBegin, strRange);
+}
+
+} // namespace tstrings
+
+
+#ifdef TSTRINGS_WITH_WCHAR
+namespace tstrings {
+
+namespace {
+/*
+ * Converts UTF16-encoded string into multi-byte string of the given encoding.
+ */
+std::string toMultiByte(const std::wstring& utf16str, int encoding) {
+    std::string reply;
+    do {
+        int cm = WideCharToMultiByte(encoding,
+                                    0,
+                                    utf16str.c_str(),
+                                    int(utf16str.size()),
+                                    NULL,
+                                    0,
+                                    NULL,
+                                    NULL);
+        if (cm < 0) {
+            JP_THROW("Unexpected reply from WideCharToMultiByte()");
+        }
+        if (0 == cm) {
+            break;
+        }
+
+        reply.resize(cm);
+        int cm2 = WideCharToMultiByte(encoding,
+                                    0,
+                                    utf16str.c_str(),
+                                    int(utf16str.size()),
+                                    &*reply.begin(),
+                                    cm,
+                                    NULL,
+                                    NULL);
+        if (cm != cm2) {
+            JP_THROW("Unexpected reply from WideCharToMultiByte()");
+        }
+    } while(0);
+
+    return reply;
+}
+
+/*
+ * Converts multi-byte string of the given encoding into UTF16-encoded string.
+ */
+std::wstring fromMultiByte(const std::string& str, int encoding) {
+    std::wstring utf16;
+    do {
+        int cw = MultiByteToWideChar(encoding,
+                                    MB_ERR_INVALID_CHARS,
+                                    str.c_str(),
+                                    int(str.size()),
+                                    NULL,
+                                    0);
+        if (cw < 0) {
+            JP_THROW("Unexpected reply from MultiByteToWideChar()");
+        }
+        if (0 == cw) {
+            break;
+        }
+
+        utf16.resize(cw);
+        int cw2 = MultiByteToWideChar(encoding,
+                                    MB_ERR_INVALID_CHARS,
+                                    str.c_str(),
+                                    int(str.size()),
+                                    &*utf16.begin(),
+                                    cw);
+        if (cw != cw2) {
+            JP_THROW("Unexpected reply from MultiByteToWideChar()");
+        }
+    } while(0);
+
+    return utf16;
+}
+} // namespace
+
+std::string toUtf8(const std::wstring& utf16str) {
+    return toMultiByte(utf16str, CP_UTF8);
+}
+
+std::wstring toUtf16(const std::string& utf8str) {
+    return fromMultiByte(utf8str, CP_UTF8);
+}
+
+} // namespace tstrings
+#endif // ifdef TSTRINGS_WITH_WCHAR
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libjpackage/tstrings.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef TSTRINGS_H
+#define TSTRINGS_H
+
+#ifdef _MSC_VER
+#   define TSTRINGS_WITH_WCHAR
+#endif
+
+#ifdef TSTRINGS_WITH_WCHAR
+#include <windows.h>
+#include <tchar.h>
+// Want compiler issue C4995 warnings for encounters of deprecated functions.
+#include <strsafe.h>
+#endif
+
+// STL's string header depends on deprecated functions.
+// We don't care about warnings from STL header, so disable them locally.
+#ifdef _MSC_VER
+#   pragma warning(push)
+#   pragma warning(disable:4995)
+#endif
+
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <vector>
+
+#ifdef _MSC_VER
+#   pragma warning(pop)
+#endif
+
+
+#ifndef _T
+#   define _T(x) x
+#endif
+
+
+#ifdef TSTRINGS_WITH_WCHAR
+typedef std::wstring        tstring;
+typedef std::wostringstream tostringstream;
+typedef std::wistringstream tistringstream;
+typedef std::wstringstream  tstringstream;
+typedef std::wistream       tistream;
+typedef std::wostream       tostream;
+typedef std::wiostream      tiostream;
+typedef std::wios           tios;
+#else
+typedef std::string         tstring;
+typedef std::ostringstream  tostringstream;
+typedef std::istringstream  tistringstream;
+typedef std::stringstream   tstringstream;
+typedef std::istream        tistream;
+typedef std::ostream        tostream;
+typedef std::iostream       tiostream;
+typedef std::ios            tios;
+
+typedef const char* LPCTSTR;
+typedef char TCHAR;
+#endif
+
+// frequently used "array of tstrings" type
+typedef std::vector<tstring> tstring_array;
+
+namespace tstrings {
+    tstring unsafe_format(tstring::const_pointer format, ...);
+
+    enum CompareType {CASE_SENSITIVE, IGNORE_CASE};
+    bool equals(const tstring& a, const tstring& b,
+            const CompareType ct=CASE_SENSITIVE);
+    bool startsWith(const tstring &str, const tstring &substr,
+            const CompareType ct=CASE_SENSITIVE);
+    bool endsWith(const tstring &str, const tstring &substr,
+            const CompareType ct=CASE_SENSITIVE);
+
+    enum SplitType {ST_ALL, ST_EXCEPT_EMPTY_STRING};
+    void split(tstring_array &strVector, const tstring &str,
+            const tstring &delimiter, const SplitType st = ST_ALL);
+    inline tstring_array split(const tstring &str, const tstring &delimiter,
+            const SplitType st = ST_ALL) {
+        tstring_array result;
+        split(result, str, delimiter, st);
+        return result;
+    }
+    tstring trim(const tstring& str, const tstring& whitespace = _T(" \t"));
+
+    /**
+     * Writes sequence of values from [b, e) range into string buffer inserting
+     * 'delimiter' after each value except of the last one.
+     * Returns contents of string buffer.
+     */
+    template <class It>
+    tstring join(It b, It e, const tstring& delimiter=tstring()) {
+        tostringstream buf;
+        if (b != e) {
+            for (;;) {
+                buf << *b;
+                if (++b == e) {
+                    break;
+                }
+                buf << delimiter;
+            }
+        }
+        return buf.str();
+    }
+
+    tstring toLower(const tstring& str);
+
+    tstring replace(const tstring &str, const tstring &search,
+            const tstring &replace);
+}
+
+
+namespace tstrings {
+    inline std::string toUtf8(const std::string& utf8str) {
+        return utf8str;
+    }
+
+#ifdef TSTRINGS_WITH_WCHAR
+    // conversion to Utf8
+    std::string toUtf8(const std::wstring& utf16str);
+
+    // conversion to Utf16
+    std::wstring toUtf16(const std::string& utf8str);
+
+    inline std::wstring fromUtf8(const std::string& utf8str) {
+        return toUtf16(utf8str);
+    }
+
+#else
+    inline std::string fromUtf8(const std::string& utf8str) {
+        return utf8str;
+    }
+#endif
+} // namespace tstrings
+
+
+namespace tstrings {
+namespace format_detail {
+
+    template <class T>
+    struct str_arg_value {
+        const tstring value;
+
+        str_arg_value(const std::string& v): value(fromUtf8(v)) {
+        }
+
+#ifdef TSTRINGS_WITH_WCHAR
+        str_arg_value(const std::wstring& v): value(v) {
+        }
+#endif
+
+        tstring::const_pointer operator () () const {
+            return value.c_str();
+        }
+    };
+
+    template <>
+    struct str_arg_value<tstring> {
+        const tstring::const_pointer value;
+
+        str_arg_value(const tstring& v): value(v.c_str()) {
+        }
+
+        str_arg_value(tstring::const_pointer v): value(v) {
+        }
+
+        tstring::const_pointer operator () () const {
+            return value;
+        }
+    };
+
+    inline str_arg_value<std::string> arg(const std::string& v) {
+        return v;
+    }
+
+    inline str_arg_value<std::string> arg(std::string::const_pointer v) {
+        return (v ? v : "(null)");
+    }
+
+#ifdef TSTRINGS_WITH_WCHAR
+    inline str_arg_value<std::wstring> arg(const std::wstring& v) {
+        return v;
+    }
+
+    inline str_arg_value<std::wstring> arg(std::wstring::const_pointer v) {
+        return (v ? v : L"(null)");
+    }
+#else
+    void arg(const std::wstring&);          // Compilation error by design.
+    void arg(std::wstring::const_pointer);  // Compilation error by design.
+#endif
+
+    template <class T>
+    struct arg_value {
+        arg_value(const T v): v(v) {
+        }
+        T operator () () const {
+            return v;
+        }
+    private:
+        const T v;
+    };
+
+    inline arg_value<int> arg(int v) {
+        return v;
+    }
+    inline arg_value<unsigned> arg(unsigned v) {
+        return v;
+    }
+    inline arg_value<long> arg(long v) {
+        return v;
+    }
+    inline arg_value<unsigned long> arg(unsigned long v) {
+        return v;
+    }
+    inline arg_value<long long> arg(long long v) {
+        return v;
+    }
+    inline arg_value<unsigned long long> arg(unsigned long long v) {
+        return v;
+    }
+    inline arg_value<float> arg(float v) {
+        return v;
+    }
+    inline arg_value<double> arg(double v) {
+        return v;
+    }
+    inline arg_value<bool> arg(bool v) {
+        return v;
+    }
+    inline arg_value<const void*> arg(const void* v) {
+        return v;
+    }
+
+} // namespace format_detail
+} // namespace tstrings
+
+
+namespace tstrings {
+    template <class T, class T2, class T3, class T4, class T5, class T6, class T7>
+    inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7) {
+        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
+                                            format_detail::arg(v2)(),
+                                            format_detail::arg(v3)(),
+                                            format_detail::arg(v4)(),
+                                            format_detail::arg(v5)(),
+                                            format_detail::arg(v6)(),
+                                            format_detail::arg(v7)());
+    }
+
+    template <class T, class T2, class T3, class T4, class T5, class T6>
+    inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6) {
+        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
+                                            format_detail::arg(v2)(),
+                                            format_detail::arg(v3)(),
+                                            format_detail::arg(v4)(),
+                                            format_detail::arg(v5)(),
+                                            format_detail::arg(v6)());
+    }
+
+    template <class T, class T2, class T3, class T4, class T5>
+    inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5) {
+        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
+                                            format_detail::arg(v2)(),
+                                            format_detail::arg(v3)(),
+                                            format_detail::arg(v4)(),
+                                            format_detail::arg(v5)());
+    }
+
+    template <class T, class T2, class T3, class T4>
+    inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4) {
+        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
+                                            format_detail::arg(v2)(),
+                                            format_detail::arg(v3)(),
+                                            format_detail::arg(v4)());
+    }
+
+    template <class T, class T2, class T3>
+    inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3) {
+        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
+                                            format_detail::arg(v2)(),
+                                            format_detail::arg(v3)());
+    }
+
+    template <class T, class T2>
+    inline tstring format(const tstring& fmt, const T& v, const T2& v2) {
+        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
+                                            format_detail::arg(v2)());
+
+    }
+
+    template <class T>
+    inline tstring format(const tstring& fmt, const T& v) {
+        return unsafe_format(fmt.c_str(),   format_detail::arg(v)());
+    }
+} // namespace tstrings
+
+
+namespace tstrings {
+    /**
+     * Buffer that accepts both std::wstring and std::string instances doing
+     * encoding conversions behind the scenes. All std::string-s assumed to be
+     * UTF8-encoded, all std::wstring-s assumed to be UTF16-encoded.
+     */
+    class any {
+    public:
+        any() {
+        }
+
+        any(std::string::const_pointer msg) {
+            data << fromUtf8(msg);
+        }
+
+        any(const std::string& msg) {
+            data << fromUtf8(msg);
+        }
+
+#ifdef TSTRINGS_WITH_WCHAR
+        any(std::wstring::const_pointer msg) {
+            data << msg;
+        }
+
+        any(const std::wstring& msg) {
+            data << msg;
+        }
+
+        any& operator << (const std::wstring& v) {
+            data << v;
+            return *this;
+        }
+
+        // need this specialization instead std::wstring::pointer,
+        // otherwise LPWSTR is handled as abstract pointer (void*)
+        any& operator << (LPWSTR v) {
+            data << (v ? v : L"NULL");
+            return *this;
+        }
+
+        // need this specialization instead std::wstring::const_pointer,
+        // otherwise LPCWSTR is handled as abstract pointer (const void*)
+        any& operator << (LPCWSTR v) {
+            data << (v ? v : L"NULL");
+            return *this;
+        }
+
+        std::wstring wstr() const {
+            return data.str();
+        }
+#endif
+
+        template <class T>
+        any& operator << (T v) {
+            data << v;
+            return *this;
+        }
+
+        any& operator << (tostream& (*pf)(tostream&)) {
+            data << pf;
+            return *this;
+        }
+
+        any& operator << (tios& (*pf)(tios&)) {
+            data << pf;
+            return *this;
+        }
+
+        any& operator << (std::ios_base& (*pf)(std::ios_base&)) {
+            data << pf;
+            return *this;
+        }
+
+        std::string str() const {
+            return toUtf8(data.str());
+        }
+
+        tstring tstr() const {
+            return data.str();
+        }
+
+    private:
+        tostringstream data;
+    };
+
+    inline tstring to_tstring(const any& val) {
+        return val.tstr();
+    }
+} // namespace tstrings
+
+
+inline std::ostream& operator << (std::ostream& os, const tstrings::any& buf) {
+    os << buf.str();
+    return os;
+}
+
+#ifdef TSTRINGS_WITH_WCHAR
+inline std::wostream& operator << (std::wostream& os, const tstrings::any& buf) {
+    os << buf.wstr();
+    return os;
+}
+#endif
+
+#endif //TSTRINGS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/libwixhelper/libwixhelper.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <Windows.h>
+#include <msiquery.h>
+#include <shlwapi.h>
+
+extern "C" {
+
+#ifdef JP_EXPORT_FUNCTION
+#error Unexpected JP_EXPORT_FUNCTION define
+#endif
+#define JP_EXPORT_FUNCTION comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
+
+    BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason,
+            LPVOID lpvReserved) {
+        return TRUE;
+    }
+
+    BOOL DirectoryExist(TCHAR *szValue) {
+        DWORD attr = GetFileAttributes(szValue);
+        if (attr == INVALID_FILE_ATTRIBUTES) {
+            return FALSE;
+        }
+
+        if (attr & FILE_ATTRIBUTE_DIRECTORY) {
+            return TRUE;
+        }
+
+        return FALSE;
+    }
+
+    UINT __stdcall CheckInstallDir(MSIHANDLE hInstall) {
+        #pragma JP_EXPORT_FUNCTION
+
+        TCHAR *szValue = NULL;
+        DWORD cchSize = 0;
+
+        UINT result = MsiGetProperty(hInstall, TEXT("INSTALLDIR"),
+                TEXT(""), &cchSize);
+        if (result == ERROR_MORE_DATA) {
+            cchSize = cchSize + 1; // NULL termination
+            szValue = new TCHAR[cchSize];
+            if (szValue) {
+                result = MsiGetProperty(hInstall, TEXT("INSTALLDIR"),
+                        szValue, &cchSize);
+            } else {
+                return ERROR_INSTALL_FAILURE;
+            }
+        }
+
+        if (result != ERROR_SUCCESS) {
+            delete [] szValue;
+            return ERROR_INSTALL_FAILURE;
+        }
+
+        if (DirectoryExist(szValue)) {
+            if (PathIsDirectoryEmpty(szValue)) {
+                MsiSetProperty(hInstall, TEXT("INSTALLDIR_VALID"), TEXT("1"));
+            } else {
+                MsiSetProperty(hInstall, TEXT("INSTALLDIR_VALID"), TEXT("0"));
+            }
+        } else {
+            MsiSetProperty(hInstall, TEXT("INSTALLDIR_VALID"), TEXT("1"));
+        }
+
+        delete [] szValue;
+
+        return ERROR_SUCCESS;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/msiwrapper/Executor.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include <algorithm>
+#include "Executor.h"
+#include "Log.h"
+#include "WinErrorHandling.h"
+
+
+namespace {
+
+void escapeArg(std::wstring& str) {
+    if (str.empty()) {
+        return;
+    }
+
+    if (str.front() == L'\"' && str.back() == L'\"' && str.size() > 1) {
+        return;
+    }
+
+    if (str.find_first_of(L" \t") != std::wstring::npos) {
+        str = L'"' + str + L'"';
+    }
+}
+
+} // namespace
+
+
+std::wstring Executor::args() const {
+    tstring_array tmpArgs;
+    // argv[0] is the module name.
+    tmpArgs.push_back(appPath);
+    tmpArgs.insert(tmpArgs.end(), argsArray.begin(), argsArray.end());
+
+    std::for_each(tmpArgs.begin(), tmpArgs.end(), escapeArg);
+    return tstrings::join(tmpArgs.begin(), tmpArgs.end(), _T(" "));
+}
+
+
+int Executor::execAndWaitForExit() const {
+    UniqueHandle h = startProcess();
+
+    const DWORD res = ::WaitForSingleObject(h.get(), INFINITE);
+    if (WAIT_FAILED ==  res) {
+        JP_THROW(SysError("WaitForSingleObject() failed", WaitForSingleObject));
+    }
+
+    DWORD exitCode = 0;
+    if (!GetExitCodeProcess(h.get(), &exitCode)) {
+        // Error reading process's exit code.
+        JP_THROW(SysError("GetExitCodeProcess() failed", GetExitCodeProcess));
+    }
+
+    const DWORD processId = GetProcessId(h.get());
+    if (!processId) {
+        JP_THROW(SysError("GetProcessId() failed.", GetProcessId));
+    }
+
+    LOG_TRACE(tstrings::any() << "Process with PID=" << processId
+                                << " terminated. Exit code=" << exitCode);
+
+    return static_cast<int>(exitCode);
+}
+
+
+UniqueHandle Executor::startProcess() const {
+    const std::wstring argsStr = args();
+
+    std::vector<TCHAR> argsBuffer(argsStr.begin(), argsStr.end());
+    argsBuffer.push_back(0); // terminating '\0'
+
+    STARTUPINFO startupInfo;
+    ZeroMemory(&startupInfo, sizeof(startupInfo));
+    startupInfo.cb = sizeof(startupInfo);
+
+    PROCESS_INFORMATION processInfo;
+    ZeroMemory(&processInfo, sizeof(processInfo));
+
+    DWORD creationFlags = 0;
+
+    if (!theVisible) {
+        // For GUI applications.
+        startupInfo.dwFlags |= STARTF_USESHOWWINDOW;
+        startupInfo.wShowWindow = SW_HIDE;
+
+        // For console applications.
+        creationFlags |= CREATE_NO_WINDOW;
+    }
+
+    tstrings::any msg;
+    msg << "CreateProcess(" << appPath << ", " << argsStr << ")";
+
+    if (!CreateProcess(appPath.c_str(), argsBuffer.data(), NULL, NULL, FALSE,
+                    creationFlags, NULL, NULL, &startupInfo, &processInfo)) {
+        msg << " failed";
+        JP_THROW(SysError(msg, CreateProcess));
+    }
+
+    msg << " succeeded; PID=" << processInfo.dwProcessId;
+    LOG_TRACE(msg);
+
+    // Close unneeded handles immediately.
+    UniqueHandle(processInfo.hThread);
+
+    // Return process handle.
+    return UniqueHandle(processInfo.hProcess);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/msiwrapper/Executor.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef EXECUTOR_H
+#define EXECUTOR_H
+
+#include "tstrings.h"
+#include "UniqueHandle.h"
+
+
+class Executor {
+public:
+    explicit Executor(const std::wstring& appPath=std::wstring()) {
+        app(appPath).visible(false);
+    }
+
+    /**
+     * Returns command line configured with arg() calls so far.
+     */
+    std::wstring args() const;
+
+    /**
+     * Set path to application to execute.
+     */
+    Executor& app(const std::wstring& v) {
+        appPath = v;
+        return *this;
+    }
+
+    /**
+     * Adds another command line argument.
+     */
+    Executor& arg(const std::wstring& v) {
+        argsArray.push_back(v);
+        return *this;
+    }
+
+    /**
+     * Controls if application window should be visible.
+     */
+    Executor& visible(bool v) {
+        theVisible = v;
+        return *this;
+    }
+
+    /**
+     * Starts application process and blocks waiting when the started
+     * process terminates.
+     * Returns process exit code.
+     * Throws exception if process start failed.
+     */
+    int execAndWaitForExit() const;
+
+private:
+    UniqueHandle startProcess() const;
+
+    bool theVisible;
+    tstring_array argsArray;
+    std::wstring appPath;
+};
+
+#endif // #ifndef EXECUTOR_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/msiwrapper/MsiWrapper.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,42 @@
+#include <algorithm>
+#include <windows.h>
+
+#include "SysInfo.h"
+#include "FileUtils.h"
+#include "Executor.h"
+#include "Resources.h"
+#include "WinErrorHandling.h"
+
+
+int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int nShowCmd)
+{
+    JP_TRY;
+
+    // Create temporary directory where to extract msi file.
+    const auto tempMsiDir = FileUtils::createTempDirectory();
+
+    // Schedule temporary directory for deletion.
+    FileUtils::Deleter cleaner;
+    cleaner.appendRecursiveDirectory(tempMsiDir);
+
+    const auto msiPath = FileUtils::mkpath() << tempMsiDir << L"main.msi";
+
+    // Extract msi file.
+    Resource(L"msi", RT_RCDATA).saveToFile(msiPath);
+
+    // Setup executor to run msiexec
+    Executor msiExecutor(SysInfo::getWIPath());
+    msiExecutor.arg(L"/i").arg(msiPath);
+    const auto args = SysInfo::getCommandArgs();
+    std::for_each(args.begin(), args.end(),
+            [&msiExecutor] (const tstring& arg) {
+        msiExecutor.arg(arg);
+    });
+
+    // Install msi file.
+    return msiExecutor.execAndWaitForExit();
+
+    JP_CATCH_ALL;
+
+    return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/msiwrapper/Resources.cpp	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include "Resources.h"
+#include "FileUtils.h"
+#include "WinErrorHandling.h"
+
+#include <fstream>
+
+
+Resource::Resource(LPCTSTR name, LPCTSTR type, HINSTANCE module) {
+    init(name, type, module);
+}
+
+Resource::Resource(UINT id, LPCTSTR type, HINSTANCE module) {
+    init(MAKEINTRESOURCE(id), type, module);
+}
+
+void Resource::init(LPCTSTR name, LPCTSTR type, HINSTANCE module) {
+    if (IS_INTRESOURCE(name)) {
+        std::wostringstream printer;
+        printer << L"#" << reinterpret_cast<size_t>(name);
+        nameStr = printer.str();
+        namePtr = name;
+    } else {
+        nameStr = name;
+        namePtr = nameStr.c_str();
+    }
+    if (IS_INTRESOURCE(type)) {
+        std::wostringstream printer;
+        printer << L"#" << reinterpret_cast<size_t>(name);
+        typeStr = printer.str();
+        typePtr = type;
+    } else {
+        typeStr = type;
+        typePtr = typeStr.c_str();
+    }
+    instance = module;
+}
+
+std::string Resource::getErrMsg(const std::string &descr) const {
+    return (tstrings::any() << descr << " (name='" << nameStr <<
+            "', type='" << typeStr << "')").str();
+}
+
+HRSRC Resource::findResource() const {
+    LPCTSTR id = namePtr;
+    // string resources are stored in blocks (stringtables)
+    // id of the resource is (stringId / 16 + 1)
+    if (typePtr == RT_STRING) {
+        id = MAKEINTRESOURCE(UINT(size_t(id) / 16 + 1));
+    }
+    return FindResource(instance, id, typePtr);
+}
+
+LPVOID Resource::getPtr(DWORD &size) const
+{
+    // LoadString returns the same result if value is zero-length or
+    // if if the value does not exists,
+    // so wee need to ensure the stringtable exists
+    HRSRC resInfo = findResource();
+    if (resInfo == NULL) {
+        JP_THROW(SysError(getErrMsg("cannot find resource"), FindResource));
+    }
+
+    HGLOBAL res = LoadResource(instance, resInfo);
+    if (res == NULL) {
+        JP_THROW(SysError(getErrMsg("cannot load resource"), LoadResource));
+    }
+
+    LPVOID ptr = LockResource(res);
+    if (res == NULL) {
+        JP_THROW(SysError(getErrMsg("cannot lock resource"), LockResource));
+    }
+
+    if (typePtr == RT_STRING) {
+        // string resources are stored in stringtables and
+        // need special handling
+        // The simplest way (while we don't need handle resource locale)
+        // is LoadString
+        // But this adds dependency on user32.dll,
+        // so implement custom string extraction
+
+        // number in the block (namePtr is an integer)
+        size_t num = size_t(namePtr) & 0xf;
+        LPWSTR strPtr = (LPWSTR)ptr;
+        for (size_t i = 0; i < num; i++) {
+            // 1st symbol contains string length
+            strPtr += DWORD(*strPtr) + 1;
+        }
+        // *strPtr contains string length, string value starts at strPtr+1
+        size = DWORD(*strPtr) * sizeof(wchar_t);
+        ptr = strPtr+1;
+    } else {
+        size = SizeofResource(instance, resInfo);
+    }
+
+    return ptr;
+}
+
+bool Resource::available() const {
+    return NULL != findResource();
+}
+
+unsigned Resource::size() const {
+    DWORD size = 0;
+    getPtr(size);
+    return size;
+}
+
+LPCVOID Resource::rawData() const {
+    DWORD size = 0;
+    return getPtr(size);
+}
+
+void Resource::saveToFile(const std::wstring &filePath) const {
+    DWORD size = 0;
+    const char *resPtr = (const char *)getPtr(size);
+
+    FileUtils::FileWriter(filePath).write(resPtr, size).finalize();
+}
+
+Resource::ByteArray Resource::binary() const {
+    DWORD size = 0;
+    LPBYTE resPtr = (LPBYTE)getPtr(size);
+    return ByteArray(resPtr, resPtr+size);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.incubator.jpackage/windows/native/msiwrapper/Resources.h	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#ifndef RESOURCES_H
+#define RESOURCES_H
+
+#include "WinSysInfo.h"
+
+
+/**
+ * Classes for resource loading.
+ * Common use cases:
+ *  - check if resource is available and save it to file:
+ *      Resource res(_T("MyResource"), _T("CustomResourceType"));
+ *      if (res.available()) {
+ *          res.saveToFile(_T("c:\\temp\\my_resource.bin"));
+ *      }
+ */
+
+class Resource {
+public:
+    // name and type can be specified by string id,
+    // by integer id (RT_* constants or MAKEINTRESOURCE)
+    Resource(LPCWSTR name, LPCWSTR type,
+            HINSTANCE module = SysInfo::getCurrentModuleHandle());
+    Resource(UINT id, LPCWSTR type,
+            HINSTANCE module = SysInfo::getCurrentModuleHandle());
+
+    bool available() const;
+
+    // all this methods throw exception if the resource is not available
+    unsigned size() const;
+    // gets raw pointer to the resource data
+    LPCVOID rawData() const;
+
+    // save the resource to a file
+    void saveToFile(const std::wstring &filePath) const;
+
+    typedef std::vector<BYTE> ByteArray;
+    // returns the resource as byte array
+    ByteArray binary() const;
+
+private:
+    std::wstring nameStr;
+    LPCWSTR namePtr;    // can be integer value or point to nameStr.c_str()
+    std::wstring typeStr;
+    LPCWSTR typePtr;    // can be integer value or point to nameStr.c_str()
+    HINSTANCE instance;
+
+    void init(LPCWSTR name, LPCWSTR type, HINSTANCE module);
+
+    // generates error message
+    std::string getErrMsg(const std::string &descr) const;
+    HRSRC findResource() const;
+    LPVOID getPtr(DWORD &size) const;
+
+private:
+    // disable copying
+    Resource(const Resource&);
+    Resource& operator = (const Resource&);
+};
+
+#endif // RESOURCES_H
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/DesktopIntegration.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,503 +0,0 @@
-/*
- * Copyright (c) 2019, 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.awt.image.BufferedImage;
-import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.*;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import javax.imageio.ImageIO;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import static jdk.jpackage.internal.LinuxAppBundler.ICON_PNG;
-import static jdk.jpackage.internal.LinuxAppImageBuilder.DEFAULT_ICON;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-/**
- * Helper to create files for desktop integration.
- */
-final class DesktopIntegration {
-
-    static final String DESKTOP_COMMANDS_INSTALL = "DESKTOP_COMMANDS_INSTALL";
-    static final String DESKTOP_COMMANDS_UNINSTALL = "DESKTOP_COMMANDS_UNINSTALL";
-    static final String UTILITY_SCRIPTS = "UTILITY_SCRIPTS";
-
-    DesktopIntegration(PlatformPackage thePackage,
-            Map<String, ? super Object> params) {
-
-        associations = FileAssociation.fetchFrom(params).stream()
-                .filter(fa -> !fa.mimeTypes.isEmpty())
-                .map(LinuxFileAssociation::new)
-                .collect(Collectors.toUnmodifiableList());
-
-        launchers = ADD_LAUNCHERS.fetchFrom(params);
-
-        this.thePackage = thePackage;
-
-        final File customIconFile = ICON_PNG.fetchFrom(params);
-
-        iconResource = createResource(DEFAULT_ICON, params)
-                .setCategory(I18N.getString("resource.menu-icon"))
-                .setExternal(customIconFile);
-        desktopFileResource = createResource("template.desktop", params)
-                .setCategory(I18N.getString("resource.menu-shortcut-descriptor"))
-                .setPublicName(APP_NAME.fetchFrom(params) + ".desktop");
-
-        // XDG recommends to use vendor prefix in desktop file names as xdg
-        // commands copy files to system directories.
-        // Package name should be a good prefix.
-        final String desktopFileName = String.format("%s-%s.desktop",
-                    thePackage.name(), APP_NAME.fetchFrom(params));
-        final String mimeInfoFileName = String.format("%s-%s-MimeInfo.xml",
-                    thePackage.name(), APP_NAME.fetchFrom(params));
-
-        mimeInfoFile = new DesktopFile(mimeInfoFileName);
-
-        if (!associations.isEmpty() || SHORTCUT_HINT.fetchFrom(params) || customIconFile != null) {
-            //
-            // Create primary .desktop file if one of conditions is met:
-            // - there are file associations configured
-            // - user explicitely requested to create a shortcut
-            // - custom icon specified
-            //
-            desktopFile = new DesktopFile(desktopFileName);
-            iconFile = new DesktopFile(APP_NAME.fetchFrom(params)
-                    + IOUtils.getSuffix(Path.of(DEFAULT_ICON)));
-        } else {
-            desktopFile = null;
-            iconFile = null;
-        }
-
-        desktopFileData = Collections.unmodifiableMap(
-                createDataForDesktopFile(params));
-
-        nestedIntegrations = launchers.stream().map(
-                launcherParams -> new DesktopIntegration(thePackage,
-                        launcherParams)).collect(Collectors.toList());
-    }
-
-    List<String> requiredPackages() {
-        return Stream.of(List.of(this), nestedIntegrations).flatMap(
-                List::stream).map(DesktopIntegration::requiredPackagesSelf).flatMap(
-                List::stream).distinct().collect(Collectors.toList());
-    }
-
-    Map<String, String> create() throws IOException {
-        associations.forEach(assoc -> assoc.data.verify());
-
-        if (iconFile != null) {
-            // Create application icon file.
-            iconResource.saveToFile(iconFile.srcPath());
-        }
-
-        Map<String, String> data = new HashMap<>(desktopFileData);
-
-        final ShellCommands shellCommands;
-        if (desktopFile != null) {
-            // Create application desktop description file.
-            createDesktopFile(data);
-
-            // Shell commands will be created only if desktop file
-            // should be installed.
-            shellCommands = new ShellCommands();
-        } else {
-            shellCommands = null;
-        }
-
-        if (!associations.isEmpty()) {
-            // Create XML file with mime types corresponding to file associations.
-            createFileAssociationsMimeInfoFile();
-
-            shellCommands.setFileAssociations();
-
-            // Create icon files corresponding to file associations
-            addFileAssociationIconFiles(shellCommands);
-        }
-
-        // Create shell commands to install/uninstall integration with desktop of the app.
-        if (shellCommands != null) {
-            shellCommands.applyTo(data);
-        }
-
-        boolean needCleanupScripts = !associations.isEmpty();
-
-        // Take care of additional launchers if there are any.
-        // Process every additional launcher as the main application launcher.
-        // Collect shell commands to install/uninstall integration with desktop
-        // of the additional launchers and append them to the corresponding
-        // commands of the main launcher.
-        List<String> installShellCmds = new ArrayList<>(Arrays.asList(
-                data.get(DESKTOP_COMMANDS_INSTALL)));
-        List<String> uninstallShellCmds = new ArrayList<>(Arrays.asList(
-                data.get(DESKTOP_COMMANDS_UNINSTALL)));
-        for (var integration: nestedIntegrations) {
-            if (!integration.associations.isEmpty()) {
-                needCleanupScripts = true;
-            }
-
-            Map<String, String> launcherData = integration.create();
-
-            installShellCmds.add(launcherData.get(DESKTOP_COMMANDS_INSTALL));
-            uninstallShellCmds.add(launcherData.get(
-                    DESKTOP_COMMANDS_UNINSTALL));
-        }
-
-        data.put(DESKTOP_COMMANDS_INSTALL, stringifyShellCommands(
-                installShellCmds));
-        data.put(DESKTOP_COMMANDS_UNINSTALL, stringifyShellCommands(
-                uninstallShellCmds));
-
-        if (needCleanupScripts) {
-            // Pull in utils.sh scrips library.
-            try (InputStream is = OverridableResource.readDefault("utils.sh");
-                    InputStreamReader isr = new InputStreamReader(is);
-                    BufferedReader reader = new BufferedReader(isr)) {
-                data.put(UTILITY_SCRIPTS, reader.lines().collect(
-                        Collectors.joining(System.lineSeparator())));
-            }
-        } else {
-            data.put(UTILITY_SCRIPTS, "");
-        }
-
-        return data;
-    }
-
-    private List<String> requiredPackagesSelf() {
-        if (desktopFile != null) {
-            return List.of("xdg-utils");
-        }
-        return Collections.emptyList();
-    }
-
-    private Map<String, String> createDataForDesktopFile(
-            Map<String, ? super Object> params) {
-        Map<String, String> data = new HashMap<>();
-        data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
-        data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
-        data.put("APPLICATION_ICON",
-                iconFile != null ? iconFile.installPath().toString() : null);
-        data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params));
-        data.put("APPLICATION_LAUNCHER",
-                thePackage.installedApplicationLayout().launchersDirectory().resolve(
-                        LinuxAppImageBuilder.getLauncherName(params)).toString());
-
-        return data;
-    }
-
-    /**
-     * Shell commands to integrate something with desktop.
-     */
-    private class ShellCommands {
-
-        ShellCommands() {
-            registerIconCmds = new ArrayList<>();
-            unregisterIconCmds = new ArrayList<>();
-
-            registerDesktopFileCmd = String.join(" ", "xdg-desktop-menu",
-                    "install", desktopFile.installPath().toString());
-            unregisterDesktopFileCmd = String.join(" ", "xdg-desktop-menu",
-                    "uninstall", desktopFile.installPath().toString());
-        }
-
-        void setFileAssociations() {
-            registerFileAssociationsCmd = String.join(" ", "xdg-mime",
-                    "install",
-                    mimeInfoFile.installPath().toString());
-            unregisterFileAssociationsCmd = String.join(" ", "xdg-mime",
-                    "uninstall", mimeInfoFile.installPath().toString());
-
-            //
-            // Add manual cleanup of system files to get rid of
-            // the default mime type handlers.
-            //
-            // Even after mime type is unregisterd with `xdg-mime uninstall`
-            // command and desktop file deleted with `xdg-desktop-menu uninstall`
-            // command, records in
-            // `/usr/share/applications/defaults.list` (Ubuntu 16) or
-            // `/usr/local/share/applications/defaults.list` (OracleLinux 7)
-            // files remain referencing deleted mime time and deleted
-            // desktop file which makes `xdg-mime query default` output name
-            // of non-existing desktop file.
-            //
-            String cleanUpCommand = String.join(" ",
-                    "uninstall_default_mime_handler",
-                    desktopFile.installPath().getFileName().toString(),
-                    String.join(" ", getMimeTypeNamesFromFileAssociations()));
-
-            unregisterFileAssociationsCmd = stringifyShellCommands(
-                    unregisterFileAssociationsCmd, cleanUpCommand);
-        }
-
-        void addIcon(String mimeType, Path iconFile) {
-            addIcon(mimeType, iconFile, getSquareSizeOfImage(iconFile.toFile()));
-        }
-
-        void addIcon(String mimeType, Path iconFile, int imgSize) {
-            imgSize = normalizeIconSize(imgSize);
-            final String dashMime = mimeType.replace('/', '-');
-            registerIconCmds.add(String.join(" ", "xdg-icon-resource",
-                    "install", "--context", "mimetypes", "--size",
-                    Integer.toString(imgSize), iconFile.toString(), dashMime));
-            unregisterIconCmds.add(String.join(" ", "xdg-icon-resource",
-                    "uninstall", dashMime, "--size", Integer.toString(imgSize)));
-        }
-
-        void applyTo(Map<String, String> data) {
-            List<String> cmds = new ArrayList<>();
-
-            cmds.add(registerDesktopFileCmd);
-            cmds.add(registerFileAssociationsCmd);
-            cmds.addAll(registerIconCmds);
-            data.put(DESKTOP_COMMANDS_INSTALL, stringifyShellCommands(cmds));
-
-            cmds.clear();
-            cmds.add(unregisterDesktopFileCmd);
-            cmds.add(unregisterFileAssociationsCmd);
-            cmds.addAll(unregisterIconCmds);
-            data.put(DESKTOP_COMMANDS_UNINSTALL, stringifyShellCommands(cmds));
-        }
-
-        private String registerDesktopFileCmd;
-        private String unregisterDesktopFileCmd;
-
-        private String registerFileAssociationsCmd;
-        private String unregisterFileAssociationsCmd;
-
-        private List<String> registerIconCmds;
-        private List<String> unregisterIconCmds;
-    }
-
-    /**
-     * Desktop integration file. xml, icon, etc.
-     * Resides somewhere in application installation tree.
-     * Has two paths:
-     *  - path where it should be placed at package build time;
-     *  - path where it should be installed by package manager;
-     */
-    private class DesktopFile {
-
-        DesktopFile(String fileName) {
-            installPath = thePackage
-                    .installedApplicationLayout()
-                    .destktopIntegrationDirectory().resolve(fileName);
-            srcPath = thePackage
-                    .sourceApplicationLayout()
-                    .destktopIntegrationDirectory().resolve(fileName);
-        }
-
-        private final Path installPath;
-        private final Path srcPath;
-
-        Path installPath() {
-            return installPath;
-        }
-
-        Path srcPath() {
-            return srcPath;
-        }
-    }
-
-    private void appendFileAssociation(XMLStreamWriter xml,
-            FileAssociation assoc) throws XMLStreamException {
-
-        for (var mimeType : assoc.mimeTypes) {
-            xml.writeStartElement("mime-type");
-            xml.writeAttribute("type", mimeType);
-
-            final String description = assoc.description;
-            if (description != null && !description.isEmpty()) {
-                xml.writeStartElement("comment");
-                xml.writeCharacters(description);
-                xml.writeEndElement();
-            }
-
-            for (String ext : assoc.extensions) {
-                xml.writeStartElement("glob");
-                xml.writeAttribute("pattern", "*." + ext);
-                xml.writeEndElement();
-            }
-
-            xml.writeEndElement();
-        }
-    }
-
-    private void createFileAssociationsMimeInfoFile() throws IOException {
-        IOUtils.createXml(mimeInfoFile.srcPath(), xml -> {
-            xml.writeStartElement("mime-info");
-            xml.writeDefaultNamespace(
-                    "http://www.freedesktop.org/standards/shared-mime-info");
-
-            for (var assoc : associations) {
-                appendFileAssociation(xml, assoc.data);
-            }
-
-            xml.writeEndElement();
-        });
-    }
-
-    private void addFileAssociationIconFiles(ShellCommands shellCommands)
-            throws IOException {
-        Set<String> processedMimeTypes = new HashSet<>();
-        for (var assoc : associations) {
-            if (assoc.iconSize <= 0) {
-                // No icon.
-                continue;
-            }
-
-            for (var mimeType : assoc.data.mimeTypes) {
-                if (processedMimeTypes.contains(mimeType)) {
-                    continue;
-                }
-
-                processedMimeTypes.add(mimeType);
-
-                // Create icon name for mime type from mime type.
-                DesktopFile faIconFile = new DesktopFile(mimeType.replace(
-                        File.separatorChar, '-') + IOUtils.getSuffix(
-                                assoc.data.iconPath));
-
-                IOUtils.copyFile(assoc.data.iconPath.toFile(),
-                        faIconFile.srcPath().toFile());
-
-                shellCommands.addIcon(mimeType, faIconFile.installPath(),
-                        assoc.iconSize);
-            }
-        }
-    }
-
-    private void createDesktopFile(Map<String, String> data) throws IOException {
-        List<String> mimeTypes = getMimeTypeNamesFromFileAssociations();
-        data.put("DESKTOP_MIMES", "MimeType=" + String.join(";", mimeTypes));
-
-        // prepare desktop shortcut
-        desktopFileResource
-                .setSubstitutionData(data)
-                .saveToFile(desktopFile.srcPath());
-    }
-
-    private List<String> getMimeTypeNamesFromFileAssociations() {
-        return associations.stream()
-                .map(fa -> fa.data.mimeTypes)
-                .flatMap(List::stream)
-                .collect(Collectors.toUnmodifiableList());
-    }
-
-    private static int getSquareSizeOfImage(File f) {
-        try {
-            BufferedImage bi = ImageIO.read(f);
-            return Math.max(bi.getWidth(), bi.getHeight());
-        } catch (IOException e) {
-            Log.verbose(e);
-        }
-        return 0;
-    }
-
-    private static int normalizeIconSize(int iconSize) {
-        // If register icon with "uncommon" size, it will be ignored.
-        // So find the best matching "common" size.
-        List<Integer> commonIconSizes = List.of(16, 22, 32, 48, 64, 128);
-
-        int idx = Collections.binarySearch(commonIconSizes, iconSize);
-        if (idx < 0) {
-            // Given icon size is greater than the largest common icon size.
-            return commonIconSizes.get(commonIconSizes.size() - 1);
-        }
-
-        if (idx == 0) {
-            // Given icon size is less or equal than the smallest common icon size.
-            return commonIconSizes.get(idx);
-        }
-
-        int commonIconSize = commonIconSizes.get(idx);
-        if (iconSize < commonIconSize) {
-            // It is better to scale down original icon than to scale it up for
-            // better visual quality.
-            commonIconSize = commonIconSizes.get(idx - 1);
-        }
-
-        return commonIconSize;
-    }
-
-    private static String stringifyShellCommands(String... commands) {
-        return stringifyShellCommands(Arrays.asList(commands));
-    }
-
-    private static String stringifyShellCommands(List<String> commands) {
-        return String.join(System.lineSeparator(), commands.stream().filter(
-                s -> s != null && !s.isEmpty()).collect(Collectors.toList()));
-    }
-
-    private static class LinuxFileAssociation {
-        LinuxFileAssociation(FileAssociation fa) {
-            this.data = fa;
-            if (fa.iconPath != null && Files.isReadable(fa.iconPath)) {
-                iconSize = getSquareSizeOfImage(fa.iconPath.toFile());
-            } else {
-                iconSize = -1;
-            }
-        }
-
-        final FileAssociation data;
-        final int iconSize;
-    }
-
-    private final PlatformPackage thePackage;
-
-    private final List<LinuxFileAssociation> associations;
-
-    private final List<Map<String, ? super Object>> launchers;
-
-    private final OverridableResource iconResource;
-    private final OverridableResource desktopFileResource;
-
-    private final DesktopFile mimeInfoFile;
-    private final DesktopFile desktopFile;
-    private final DesktopFile iconFile;
-
-    private final List<DesktopIntegration> nestedIntegrations;
-
-    private final Map<String, String> desktopFileData;
-
-    private static final BundlerParamInfo<String> MENU_GROUP =
-        new StandardBundlerParam<>(
-                Arguments.CLIOptions.LINUX_MENU_GROUP.getId(),
-                String.class,
-                params -> I18N.getString("param.menu-group.default"),
-                (s, p) -> s
-        );
-
-    private static final StandardBundlerParam<Boolean> SHORTCUT_HINT =
-        new StandardBundlerParam<>(
-                Arguments.CLIOptions.LINUX_SHORTCUT_HINT.getId(),
-                Boolean.class,
-                params -> false,
-                (s, p) -> (s == null || "null".equalsIgnoreCase(s))
-                        ? false : Boolean.valueOf(s)
-        );
-}
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LibProvidersLookup.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2019, 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.Files;
-import java.nio.file.Path;
-import java.util.*;
-import java.util.function.Predicate;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * Builds list of packages providing dynamic libraries for the given set of files.
- */
-final public class LibProvidersLookup {
-    static boolean supported() {
-        return (new ToolValidator(TOOL_LDD).validate() == null);
-    }
-
-    public LibProvidersLookup() {
-    }
-
-    LibProvidersLookup setPackageLookup(PackageLookup v) {
-        packageLookup = v;
-        return this;
-    }
-
-    List<String> execute(Path root) throws IOException {
-        // Get the list of files in the root for which to look up for needed shared libraries
-        List<Path> allPackageFiles;
-        try (Stream<Path> stream = Files.walk(root)) {
-            allPackageFiles = stream.filter(Files::isRegularFile).filter(
-                    LibProvidersLookup::canDependOnLibs).collect(
-                    Collectors.toList());
-        }
-
-        Collection<Path> neededLibs = getNeededLibsForFiles(allPackageFiles);
-
-        // Get the list of unique package names.
-        List<String> neededPackages = neededLibs.stream().map(libPath -> {
-            try {
-                List<String> packageNames = packageLookup.apply(libPath).filter(
-                        Objects::nonNull).filter(Predicate.not(String::isBlank)).distinct().collect(
-                        Collectors.toList());
-                Log.verbose(String.format("%s is provided by %s", libPath, packageNames));
-                return packageNames;
-            } catch (IOException ex) {
-                // Ignore and keep going
-                Log.verbose(ex);
-                List<String> packageNames = Collections.emptyList();
-                return packageNames;
-            }
-        }).flatMap(List::stream).sorted().distinct().collect(Collectors.toList());
-
-        return neededPackages;
-    }
-
-    private static List<Path> getNeededLibsForFile(Path path) throws IOException {
-        List<Path> result = new ArrayList<>();
-        int ret = Executor.of(TOOL_LDD, path.toString()).setOutputConsumer(lines -> {
-            lines.map(line -> {
-                Matcher matcher = LIB_IN_LDD_OUTPUT_REGEX.matcher(line);
-                if (matcher.find()) {
-                    return matcher.group(1);
-                }
-                return null;
-            }).filter(Objects::nonNull).map(Path::of).forEach(result::add);
-        }).execute();
-
-        if (ret != 0) {
-            // objdump failed. This is OK if the tool was applied to not a binary file
-            return Collections.emptyList();
-        }
-
-        return result;
-    }
-
-    private static Collection<Path> getNeededLibsForFiles(List<Path> paths) {
-        // Depending on tool used, the set can contain full paths (ldd) or
-        // only file names (objdump).
-        Set<Path> allLibs = paths.stream().map(path -> {
-            List<Path> libs;
-            try {
-                libs = getNeededLibsForFile(path);
-            } catch (IOException ex) {
-                Log.verbose(ex);
-                libs = Collections.emptyList();
-            }
-            return libs;
-        }).flatMap(List::stream).collect(Collectors.toSet());
-
-        // `allLibs` contains names of all .so needed by files from `paths` list.
-        // If there are mutual dependencies between binaries from `paths` list,
-        // then names or full paths to these binaries are in `allLibs` set.
-        // Remove these items from `allLibs`.
-        Set<Path> excludedNames = paths.stream().map(Path::getFileName).collect(
-                Collectors.toSet());
-        Iterator<Path> it = allLibs.iterator();
-        while (it.hasNext()) {
-            Path libName = it.next().getFileName();
-            if (excludedNames.contains(libName)) {
-                it.remove();
-            }
-        }
-
-        return allLibs;
-    }
-
-    private static boolean canDependOnLibs(Path path) {
-        return path.toFile().canExecute() || path.toString().endsWith(".so");
-    }
-
-    @FunctionalInterface
-    public interface PackageLookup {
-        Stream<String> apply(Path path) throws IOException;
-    }
-
-    private PackageLookup packageLookup;
-
-    private static final String TOOL_LDD = "ldd";
-
-    //
-    // Typical ldd output:
-    //
-    // ldd: warning: you do not have execution permission for `/tmp/jdk.jpackage17911687595930080396/images/opt/simplepackagetest/lib/runtime/lib/libawt_headless.so'
-    //  linux-vdso.so.1 =>  (0x00007ffce6bfd000)
-    //  libawt.so => /tmp/jdk.jpackage17911687595930080396/images/opt/simplepackagetest/lib/runtime/lib/libawt.so (0x00007f4e00c75000)
-    //  libjvm.so => not found
-    //  libjava.so => /tmp/jdk.jpackage17911687595930080396/images/opt/simplepackagetest/lib/runtime/lib/libjava.so (0x00007f4e00c41000)
-    //  libm.so.6 => /lib64/libm.so.6 (0x00007f4e00834000)
-    //  libdl.so.2 => /lib64/libdl.so.2 (0x00007f4e00630000)
-    //  libc.so.6 => /lib64/libc.so.6 (0x00007f4e00262000)
-    //  libjvm.so => not found
-    //  libjvm.so => not found
-    //  libverify.so => /tmp/jdk.jpackage17911687595930080396/images/opt/simplepackagetest/lib/runtime/lib/libverify.so (0x00007f4e00c2e000)
-    //  /lib64/ld-linux-x86-64.so.2 (0x00007f4e00b36000)
-    //  libjvm.so => not found
-    //
-    private static final Pattern LIB_IN_LDD_OUTPUT_REGEX = Pattern.compile(
-            "^\\s*\\S+\\s*=>\\s*(\\S+)\\s+\\(0[xX]\\p{XDigit}+\\)");
-}
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.File;
-import java.text.MessageFormat;
-import java.util.*;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-public class LinuxAppBundler extends AbstractImageBundler {
-
-    static final BundlerParamInfo<File> ICON_PNG =
-            new StandardBundlerParam<>(
-            "icon.png",
-            File.class,
-            params -> {
-                File f = ICON.fetchFrom(params);
-                if (f != null && !f.getName().toLowerCase().endsWith(".png")) {
-                    Log.error(MessageFormat.format(
-                            I18N.getString("message.icon-not-png"), f));
-                    return null;
-                }
-                return f;
-            },
-            (s, p) -> new File(s));
-
-    static final BundlerParamInfo<String> LINUX_INSTALL_DIR =
-            new StandardBundlerParam<>(
-            "linux-install-dir",
-            String.class,
-            params -> {
-                 String dir = INSTALL_DIR.fetchFrom(params);
-                 if (dir != null) {
-                     if (dir.endsWith("/")) {
-                         dir = dir.substring(0, dir.length()-1);
-                     }
-                     return dir;
-                 }
-                 return "/opt";
-             },
-            (s, p) -> s
-    );
-
-    static final BundlerParamInfo<String> LINUX_PACKAGE_DEPENDENCIES =
-            new StandardBundlerParam<>(
-            Arguments.CLIOptions.LINUX_PACKAGE_DEPENDENCIES.getId(),
-            String.class,
-            params -> {
-                 return "";
-             },
-            (s, p) -> s
-    );
-
-    @Override
-    public boolean validate(Map<String, ? super Object> params)
-            throws ConfigException {
-        try {
-            Objects.requireNonNull(params);
-            return doValidate(params);
-        } catch (RuntimeException re) {
-            if (re.getCause() instanceof ConfigException) {
-                throw (ConfigException) re.getCause();
-            } else {
-                throw new ConfigException(re);
-            }
-        }
-    }
-
-    private boolean doValidate(Map<String, ? super Object> params)
-            throws ConfigException {
-
-        imageBundleValidation(params);
-
-        return true;
-    }
-
-    File doBundle(Map<String, ? super Object> params, File outputDirectory,
-            boolean dependentTask) throws PackagerException {
-        if (StandardBundlerParam.isRuntimeInstaller(params)) {
-            return PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
-        } else {
-            return doAppBundle(params, outputDirectory, dependentTask);
-        }
-    }
-
-    private File doAppBundle(Map<String, ? super Object> params,
-            File outputDirectory, boolean dependentTask)
-            throws PackagerException {
-        try {
-            File rootDirectory = createRoot(params, outputDirectory,
-                    dependentTask, APP_NAME.fetchFrom(params));
-            AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder(
-                    params, outputDirectory.toPath());
-            if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(params) == null ) {
-                JLinkBundlerHelper.execute(params, appBuilder);
-            } else {
-                StandardBundlerParam.copyPredefinedRuntimeImage(
-                        params, appBuilder);
-            }
-            return rootDirectory;
-        } catch (PackagerException pe) {
-            throw pe;
-        } catch (Exception ex) {
-            Log.verbose(ex);
-            throw new PackagerException(ex);
-        }
-    }
-
-    @Override
-    public String getName() {
-        return I18N.getString("app.bundler.name");
-    }
-
-    @Override
-    public String getID() {
-        return "linux.app";
-    }
-
-    @Override
-    public String getBundleType() {
-        return "IMAGE";
-    }
-
-    @Override
-    public File execute(Map<String, ? super Object> params,
-            File outputParentDir) throws PackagerException {
-        return doBundle(params, outputParentDir, false);
-    }
-
-    @Override
-    public boolean supported(boolean runtimeInstaller) {
-        return true;
-    }
-
-    @Override
-    public boolean isDefault() {
-        return false;
-    }
-
-}
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
-
-    private static final String LIBRARY_NAME = "libapplauncher.so";
-    final static String DEFAULT_ICON = "java32.png";
-
-    private final ApplicationLayout appLayout;
-
-    public static final BundlerParamInfo<File> ICON_PNG =
-            new StandardBundlerParam<>(
-            "icon.png",
-            File.class,
-            params -> {
-                File f = ICON.fetchFrom(params);
-                if (f != null && !f.getName().toLowerCase().endsWith(".png")) {
-                    Log.error(MessageFormat.format(I18N.getString(
-                            "message.icon-not-png"), f));
-                    return null;
-                }
-                return f;
-            },
-            (s, p) -> new File(s));
-
-    private static ApplicationLayout createAppLayout(Map<String, Object> params,
-            Path imageOutDir) {
-        return ApplicationLayout.linuxAppImage().resolveAt(
-                imageOutDir.resolve(APP_NAME.fetchFrom(params)));
-    }
-
-    public LinuxAppImageBuilder(Map<String, Object> params, Path imageOutDir)
-            throws IOException {
-        super(params, createAppLayout(params, imageOutDir).runtimeDirectory());
-
-        appLayout = createAppLayout(params, imageOutDir);
-    }
-
-    private void writeEntry(InputStream in, Path dstFile) throws IOException {
-        Files.createDirectories(dstFile.getParent());
-        Files.copy(in, dstFile);
-    }
-
-    public static String getLauncherName(Map<String, ? super Object> params) {
-        return APP_NAME.fetchFrom(params);
-    }
-
-    private Path getLauncherCfgPath(Map<String, ? super Object> params) {
-        return appLayout.appDirectory().resolve(
-                APP_NAME.fetchFrom(params) + ".cfg");
-    }
-
-    @Override
-    public Path getAppDir() {
-        return appLayout.appDirectory();
-    }
-
-    @Override
-    public Path getAppModsDir() {
-        return appLayout.appModsDirectory();
-    }
-
-    @Override
-    protected String getCfgAppDir() {
-        return Path.of("$ROOTDIR").resolve(
-                ApplicationLayout.linuxAppImage().appDirectory()).toString()
-                + File.separator;
-    }
-
-    @Override
-    protected String getCfgRuntimeDir() {
-        return Path.of("$ROOTDIR").resolve(
-              ApplicationLayout.linuxAppImage().runtimeDirectory()).toString();
-    }
-
-    @Override
-    public void prepareApplicationFiles(Map<String, ? super Object> params)
-            throws IOException {
-        Map<String, ? super Object> originalParams = new HashMap<>(params);
-
-        appLayout.roots().stream().forEach(dir -> {
-            try {
-                IOUtils.writableOutputDir(dir);
-            } catch (PackagerException pe) {
-                throw new RuntimeException(pe);
-            }
-        });
-
-        // create the primary launcher
-        createLauncherForEntryPoint(params);
-
-        // Copy library to the launcher folder
-        try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
-            writeEntry(is_lib, appLayout.dllDirectory().resolve(LIBRARY_NAME));
-        }
-
-        // create the additional launchers, if any
-        List<Map<String, ? super Object>> entryPoints
-                = StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
-        for (Map<String, ? super Object> entryPoint : entryPoints) {
-            createLauncherForEntryPoint(
-                    AddLauncherArguments.merge(originalParams, entryPoint));
-        }
-
-        // Copy class path entries to Java folder
-        copyApplication(params);
-
-        // Copy icon to Resources folder
-        copyIcon(params);
-    }
-
-    @Override
-    public void prepareJreFiles(Map<String, ? super Object> params)
-            throws IOException {}
-
-    private void createLauncherForEntryPoint(
-            Map<String, ? super Object> params) throws IOException {
-        // Copy executable to launchers folder
-        Path executableFile = appLayout.launchersDirectory().resolve(getLauncherName(params));
-        try (InputStream is_launcher =
-                getResourceAsStream("jpackageapplauncher")) {
-            writeEntry(is_launcher, executableFile);
-        }
-
-        executableFile.toFile().setExecutable(true, false);
-        executableFile.toFile().setWritable(true, true);
-
-        writeCfgFile(params, getLauncherCfgPath(params).toFile());
-    }
-
-    private void copyIcon(Map<String, ? super Object> params)
-            throws IOException {
-
-        Path iconTarget = appLayout.destktopIntegrationDirectory().resolve(
-                APP_NAME.fetchFrom(params) + IOUtils.getSuffix(Path.of(
-                DEFAULT_ICON)));
-
-        createResource(DEFAULT_ICON, params)
-                .setCategory("icon")
-                .setExternal(ICON_PNG.fetchFrom(params))
-                .saveToFile(iconTarget);
-    }
-
-    private void copyApplication(Map<String, ? super Object> params)
-            throws IOException {
-        for (RelativeFileSet appResources :
-                APP_RESOURCES_LIST.fetchFrom(params)) {
-            if (appResources == null) {
-                throw new RuntimeException("Null app resources?");
-            }
-            File srcdir = appResources.getBaseDirectory();
-            for (String fname : appResources.getIncludedFiles()) {
-                copyEntry(appLayout.appDirectory(), srcdir, fname);
-            }
-        }
-    }
-
-}
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxDebBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,487 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.*;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-
-import java.nio.file.attribute.PosixFilePermission;
-import java.nio.file.attribute.PosixFilePermissions;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import static jdk.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-
-public class LinuxDebBundler extends LinuxPackageBundler {
-
-    // Debian rules for package naming are used here
-    // https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
-    //
-    // Package names must consist only of lower case letters (a-z),
-    // digits (0-9), plus (+) and minus (-) signs, and periods (.).
-    // They must be at least two characters long and
-    // must start with an alphanumeric character.
-    //
-    private static final Pattern DEB_PACKAGE_NAME_PATTERN =
-            Pattern.compile("^[a-z][a-z\\d\\+\\-\\.]+");
-
-    private static final BundlerParamInfo<String> PACKAGE_NAME =
-            new StandardBundlerParam<> (
-            Arguments.CLIOptions.LINUX_BUNDLE_NAME.getId(),
-            String.class,
-            params -> {
-                String nm = APP_NAME.fetchFrom(params);
-
-                if (nm == null) return null;
-
-                // make sure to lower case and spaces/underscores become dashes
-                nm = nm.toLowerCase().replaceAll("[ _]", "-");
-                return nm;
-            },
-            (s, p) -> {
-                if (!DEB_PACKAGE_NAME_PATTERN.matcher(s).matches()) {
-                    throw new IllegalArgumentException(new ConfigException(
-                            MessageFormat.format(I18N.getString(
-                            "error.invalid-value-for-package-name"), s),
-                            I18N.getString(
-                            "error.invalid-value-for-package-name.advice")));
-                }
-
-                return s;
-            });
-
-    private final static String TOOL_DPKG_DEB = "dpkg-deb";
-    private final static String TOOL_DPKG = "dpkg";
-    private final static String TOOL_FAKEROOT = "fakeroot";
-
-    private final static String DEB_ARCH;
-    static {
-        String debArch;
-        try {
-            debArch = Executor.of(TOOL_DPKG, "--print-architecture").saveOutput(
-                    true).executeExpectSuccess().getOutput().get(0);
-        } catch (IOException ex) {
-            debArch = null;
-        }
-        DEB_ARCH = debArch;
-    }
-
-    private static final BundlerParamInfo<String> FULL_PACKAGE_NAME =
-            new StandardBundlerParam<>(
-                    "linux.deb.fullPackageName", String.class, params -> {
-                        return PACKAGE_NAME.fetchFrom(params)
-                            + "_" + VERSION.fetchFrom(params)
-                            + "-" + RELEASE.fetchFrom(params)
-                            + "_" + DEB_ARCH;
-                    }, (s, p) -> s);
-
-    private static final BundlerParamInfo<String> EMAIL =
-            new StandardBundlerParam<> (
-            Arguments.CLIOptions.LINUX_DEB_MAINTAINER.getId(),
-            String.class,
-            params -> "Unknown",
-            (s, p) -> s);
-
-    private static final BundlerParamInfo<String> MAINTAINER =
-            new StandardBundlerParam<> (
-            BundleParams.PARAM_MAINTAINER,
-            String.class,
-            params -> VENDOR.fetchFrom(params) + " <"
-                    + EMAIL.fetchFrom(params) + ">",
-            (s, p) -> s);
-
-    private static final BundlerParamInfo<String> SECTION =
-            new StandardBundlerParam<>(
-            Arguments.CLIOptions.LINUX_CATEGORY.getId(),
-            String.class,
-            params -> "misc",
-            (s, p) -> s);
-
-    private static final BundlerParamInfo<String> LICENSE_TEXT =
-            new StandardBundlerParam<> (
-            "linux.deb.licenseText",
-            String.class,
-            params -> {
-                try {
-                    String licenseFile = LICENSE_FILE.fetchFrom(params);
-                    if (licenseFile != null) {
-                        return Files.readString(Path.of(licenseFile));
-                    }
-                } catch (IOException e) {
-                    Log.verbose(e);
-                }
-                return "Unknown";
-            },
-            (s, p) -> s);
-
-    public LinuxDebBundler() {
-        super(PACKAGE_NAME);
-    }
-
-    @Override
-    public void doValidate(Map<String, ? super Object> params)
-            throws ConfigException {
-
-        // Show warning if license file is missing
-        if (LICENSE_FILE.fetchFrom(params) == null) {
-            Log.verbose(I18N.getString("message.debs-like-licenses"));
-        }
-    }
-
-    @Override
-    protected List<ToolValidator> getToolValidators(
-            Map<String, ? super Object> params) {
-        return Stream.of(TOOL_DPKG_DEB, TOOL_DPKG, TOOL_FAKEROOT).map(
-                ToolValidator::new).collect(Collectors.toList());
-    }
-
-    @Override
-    protected File buildPackageBundle(
-            Map<String, String> replacementData,
-            Map<String, ? super Object> params, File outputParentDir) throws
-            PackagerException, IOException {
-
-        prepareProjectConfig(replacementData, params);
-        adjustPermissionsRecursive(createMetaPackage(params).sourceRoot().toFile());
-        return buildDeb(params, outputParentDir);
-    }
-
-    private static final Pattern PACKAGE_NAME_REGEX = Pattern.compile("^(^\\S+):");
-
-    @Override
-    protected void initLibProvidersLookup(
-            Map<String, ? super Object> params,
-            LibProvidersLookup libProvidersLookup) {
-
-        //
-        // `dpkg -S` command does glob pattern lookup. If not the absolute path
-        // to the file is specified it might return mltiple package names.
-        // Even for full paths multiple package names can be returned as
-        // it is OK for multiple packages to provide the same file. `/opt`
-        // directory is such an example. So we have to deal with multiple
-        // packages per file situation.
-        //
-        // E.g.: `dpkg -S libc.so.6` command reports three packages:
-        // libc6-x32: /libx32/libc.so.6
-        // libc6:amd64: /lib/x86_64-linux-gnu/libc.so.6
-        // libc6-i386: /lib32/libc.so.6
-        // `:amd64` is architecture suffix and can (should) be dropped.
-        // Still need to decide what package to choose from three.
-        // libc6-x32 and libc6-i386 both depend on libc6:
-        // $ dpkg -s libc6-x32
-        // Package: libc6-x32
-        // Status: install ok installed
-        // Priority: optional
-        // Section: libs
-        // Installed-Size: 10840
-        // Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
-        // Architecture: amd64
-        // Source: glibc
-        // Version: 2.23-0ubuntu10
-        // Depends: libc6 (= 2.23-0ubuntu10)
-        //
-        // We can dive into tracking dependencies, but this would be overly
-        // complicated.
-        //
-        // For simplicity lets consider the following rules:
-        // 1. If there is one item in `dpkg -S` output, accept it.
-        // 2. If there are multiple items in `dpkg -S` output and there is at
-        //  least one item with the default arch suffix (DEB_ARCH),
-        //  accept only these items.
-        // 3. If there are multiple items in `dpkg -S` output and there are
-        //  no with the default arch suffix (DEB_ARCH), accept all items.
-        // So lets use this heuristics: don't accept packages for whom
-        //  `dpkg -p` command fails.
-        // 4. Arch suffix should be stripped from accepted package names.
-        //
-
-        libProvidersLookup.setPackageLookup(file -> {
-            Set<String> archPackages = new HashSet<>();
-            Set<String> otherPackages = new HashSet<>();
-
-            Executor.of(TOOL_DPKG, "-S", file.toString())
-                    .saveOutput(true).executeExpectSuccess()
-                    .getOutput().forEach(line -> {
-                        Matcher matcher = PACKAGE_NAME_REGEX.matcher(line);
-                        if (matcher.find()) {
-                            String name = matcher.group(1);
-                            if (name.endsWith(":" + DEB_ARCH)) {
-                                // Strip arch suffix
-                                name = name.substring(0,
-                                        name.length() - (DEB_ARCH.length() + 1));
-                                archPackages.add(name);
-                            } else {
-                                otherPackages.add(name);
-                            }
-                        }
-                    });
-
-            if (!archPackages.isEmpty()) {
-                return archPackages.stream();
-            }
-            return otherPackages.stream();
-        });
-    }
-
-    @Override
-    protected List<ConfigException> verifyOutputBundle(
-            Map<String, ? super Object> params, Path packageBundle) {
-        List<ConfigException> errors = new ArrayList<>();
-
-        String controlFileName = "control";
-
-        List<PackageProperty> properties = List.of(
-                new PackageProperty("Package", PACKAGE_NAME.fetchFrom(params),
-                        "APPLICATION_PACKAGE", controlFileName),
-                new PackageProperty("Version", String.format("%s-%s",
-                        VERSION.fetchFrom(params), RELEASE.fetchFrom(params)),
-                        "APPLICATION_VERSION-APPLICATION_RELEASE",
-                        controlFileName),
-                new PackageProperty("Architecture", DEB_ARCH, "APPLICATION_ARCH",
-                        controlFileName));
-
-        List<String> cmdline = new ArrayList<>(List.of(TOOL_DPKG_DEB, "-f",
-                packageBundle.toString()));
-        properties.forEach(property -> cmdline.add(property.name));
-        try {
-            Map<String, String> actualValues = Executor.of(cmdline.toArray(String[]::new))
-                    .saveOutput(true)
-                    .executeExpectSuccess()
-                    .getOutput().stream()
-                            .map(line -> line.split(":\\s+", 2))
-                            .collect(Collectors.toMap(
-                                    components -> components[0],
-                                    components -> components[1]));
-            properties.forEach(property -> errors.add(property.verifyValue(
-                    actualValues.get(property.name))));
-        } catch (IOException ex) {
-            // Ignore error as it is not critical. Just report it.
-            Log.verbose(ex);
-        }
-
-        return errors;
-    }
-
-    /*
-     * set permissions with a string like "rwxr-xr-x"
-     *
-     * This cannot be directly backport to 22u which is built with 1.6
-     */
-    private void setPermissions(File file, String permissions) {
-        Set<PosixFilePermission> filePermissions =
-                PosixFilePermissions.fromString(permissions);
-        try {
-            if (file.exists()) {
-                Files.setPosixFilePermissions(file.toPath(), filePermissions);
-            }
-        } catch (IOException ex) {
-            Log.error(ex.getMessage());
-            Log.verbose(ex);
-        }
-
-    }
-
-    public static boolean isDebian() {
-        // we are just going to run "dpkg -s coreutils" and assume Debian
-        // or deritive if no error is returned.
-        try {
-            Executor.of(TOOL_DPKG, "-s", "coreutils").executeExpectSuccess();
-            return true;
-        } catch (IOException e) {
-            // just fall thru
-        }
-        return false;
-    }
-
-    private void adjustPermissionsRecursive(File dir) throws IOException {
-        Files.walkFileTree(dir.toPath(), new SimpleFileVisitor<Path>() {
-            @Override
-            public FileVisitResult visitFile(Path file,
-                    BasicFileAttributes attrs)
-                    throws IOException {
-                if (file.endsWith(".so") || !Files.isExecutable(file)) {
-                    setPermissions(file.toFile(), "rw-r--r--");
-                } else if (Files.isExecutable(file)) {
-                    setPermissions(file.toFile(), "rwxr-xr-x");
-                }
-                return FileVisitResult.CONTINUE;
-            }
-
-            @Override
-            public FileVisitResult postVisitDirectory(Path dir, IOException e)
-                    throws IOException {
-                if (e == null) {
-                    setPermissions(dir.toFile(), "rwxr-xr-x");
-                    return FileVisitResult.CONTINUE;
-                } else {
-                    // directory iteration failed
-                    throw e;
-                }
-            }
-        });
-    }
-
-    private class DebianFile {
-
-        DebianFile(Path dstFilePath, String comment) {
-            this.dstFilePath = dstFilePath;
-            this.comment = comment;
-        }
-
-        DebianFile setExecutable() {
-            permissions = "rwxr-xr-x";
-            return this;
-        }
-
-        void create(Map<String, String> data, Map<String, ? super Object> params)
-                throws IOException {
-            createResource("template." + dstFilePath.getFileName().toString(),
-                    params)
-                    .setCategory(I18N.getString(comment))
-                    .setSubstitutionData(data)
-                    .saveToFile(dstFilePath);
-            if (permissions != null) {
-                setPermissions(dstFilePath.toFile(), permissions);
-            }
-        }
-
-        private final Path dstFilePath;
-        private final String comment;
-        private String permissions;
-    }
-
-    private void prepareProjectConfig(Map<String, String> data,
-            Map<String, ? super Object> params) throws IOException {
-
-        Path configDir = createMetaPackage(params).sourceRoot().resolve("DEBIAN");
-        List<DebianFile> debianFiles = new ArrayList<>();
-        debianFiles.add(new DebianFile(
-                configDir.resolve("control"),
-                "resource.deb-control-file"));
-        debianFiles.add(new DebianFile(
-                configDir.resolve("preinst"),
-                "resource.deb-preinstall-script").setExecutable());
-        debianFiles.add(new DebianFile(
-                configDir.resolve("prerm"),
-                "resource.deb-prerm-script").setExecutable());
-        debianFiles.add(new DebianFile(
-                configDir.resolve("postinst"),
-                "resource.deb-postinstall-script").setExecutable());
-        debianFiles.add(new DebianFile(
-                configDir.resolve("postrm"),
-                "resource.deb-postrm-script").setExecutable());
-
-        if (!StandardBundlerParam.isRuntimeInstaller(params)) {
-            debianFiles.add(new DebianFile(
-                    getConfig_CopyrightFile(params).toPath(),
-                    "resource.copyright-file"));
-        }
-
-        for (DebianFile debianFile : debianFiles) {
-            debianFile.create(data, params);
-        }
-    }
-
-    @Override
-    protected Map<String, String> createReplacementData(
-            Map<String, ? super Object> params) throws IOException {
-        Map<String, String> data = new HashMap<>();
-
-        data.put("APPLICATION_MAINTAINER", MAINTAINER.fetchFrom(params));
-        data.put("APPLICATION_SECTION", SECTION.fetchFrom(params));
-        data.put("APPLICATION_COPYRIGHT", COPYRIGHT.fetchFrom(params));
-        data.put("APPLICATION_LICENSE_TEXT", LICENSE_TEXT.fetchFrom(params));
-        data.put("APPLICATION_ARCH", DEB_ARCH);
-        data.put("APPLICATION_INSTALLED_SIZE", Long.toString(
-                createMetaPackage(params).sourceApplicationLayout().sizeInBytes() >> 10));
-
-        return data;
-    }
-
-    private File getConfig_CopyrightFile(Map<String, ? super Object> params) {
-        PlatformPackage thePackage = createMetaPackage(params);
-        return thePackage.sourceRoot().resolve(Path.of(".",
-                LINUX_INSTALL_DIR.fetchFrom(params), PACKAGE_NAME.fetchFrom(
-                params), "share/doc/copyright")).toFile();
-    }
-
-    private File buildDeb(Map<String, ? super Object> params,
-            File outdir) throws IOException {
-        File outFile = new File(outdir,
-                FULL_PACKAGE_NAME.fetchFrom(params)+".deb");
-        Log.verbose(MessageFormat.format(I18N.getString(
-                "message.outputting-to-location"), outFile.getAbsolutePath()));
-
-        PlatformPackage thePackage = createMetaPackage(params);
-
-        List<String> cmdline = new ArrayList<>();
-        cmdline.addAll(List.of(TOOL_FAKEROOT, TOOL_DPKG_DEB));
-        if (Log.isVerbose()) {
-            cmdline.add("--verbose");
-        }
-        cmdline.addAll(List.of("-b", thePackage.sourceRoot().toString(),
-                outFile.getAbsolutePath()));
-
-        // run dpkg
-        Executor.of(cmdline.toArray(String[]::new)).executeExpectSuccess();
-
-        Log.verbose(MessageFormat.format(I18N.getString(
-                "message.output-to-location"), outFile.getAbsolutePath()));
-
-        return outFile;
-    }
-
-    @Override
-    public String getName() {
-        return I18N.getString("deb.bundler.name");
-    }
-
-    @Override
-    public String getID() {
-        return "deb";
-    }
-
-    @Override
-    public boolean supported(boolean runtimeInstaller) {
-        return Platform.isLinux() && (new ToolValidator(TOOL_DPKG_DEB).validate() == null);
-    }
-
-    @Override
-    public boolean isDefault() {
-        return isDebian();
-    }
-}
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxPackageBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,357 +0,0 @@
-/*
- * Copyright (c) 2019, 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.*;
-import java.nio.file.InvalidPathException;
-import java.nio.file.Path;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import static jdk.jpackage.internal.DesktopIntegration.*;
-import static jdk.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
-import static jdk.jpackage.internal.LinuxAppBundler.LINUX_PACKAGE_DEPENDENCIES;
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-
-abstract class LinuxPackageBundler extends AbstractBundler {
-
-    LinuxPackageBundler(BundlerParamInfo<String> packageName) {
-        this.packageName = packageName;
-    }
-
-    @Override
-    final public boolean validate(Map<String, ? super Object> params)
-            throws ConfigException {
-
-        // run basic validation to ensure requirements are met
-        // we are not interested in return code, only possible exception
-        APP_BUNDLER.fetchFrom(params).validate(params);
-
-        validateInstallDir(LINUX_INSTALL_DIR.fetchFrom(params));
-
-        validateFileAssociations(FILE_ASSOCIATIONS.fetchFrom(params));
-
-        // If package name has some restrictions, the string converter will
-        // throw an exception if invalid
-        packageName.getStringConverter().apply(packageName.fetchFrom(params),
-            params);
-
-        for (var validator: getToolValidators(params)) {
-            ConfigException ex = validator.validate();
-            if (ex != null) {
-                throw ex;
-            }
-        }
-
-        withFindNeededPackages = LibProvidersLookup.supported();
-        if (!withFindNeededPackages) {
-            final String advice;
-            if ("deb".equals(getID())) {
-                advice = "message.deb-ldd-not-available.advice";
-            } else {
-                advice = "message.rpm-ldd-not-available.advice";
-            }
-            // Let user know package dependencies will not be generated.
-            Log.error(String.format("%s\n%s", I18N.getString(
-                    "message.ldd-not-available"), I18N.getString(advice)));
-        }
-
-        // Packaging specific validation
-        doValidate(params);
-
-        return true;
-    }
-
-    @Override
-    final public String getBundleType() {
-        return "INSTALLER";
-    }
-
-    @Override
-    final public File execute(Map<String, ? super Object> params,
-            File outputParentDir) throws PackagerException {
-        IOUtils.writableOutputDir(outputParentDir.toPath());
-
-        PlatformPackage thePackage = createMetaPackage(params);
-
-        Function<File, ApplicationLayout> initAppImageLayout = imageRoot -> {
-            ApplicationLayout layout = appImageLayout(params);
-            layout.pathGroup().setPath(new Object(),
-                    AppImageFile.getPathInAppImage(Path.of("")));
-            return layout.resolveAt(imageRoot.toPath());
-        };
-
-        try {
-            File appImage = StandardBundlerParam.getPredefinedAppImage(params);
-
-            // we either have an application image or need to build one
-            if (appImage != null) {
-                initAppImageLayout.apply(appImage).copy(
-                        thePackage.sourceApplicationLayout());
-            } else {
-                appImage = APP_BUNDLER.fetchFrom(params).doBundle(params,
-                        thePackage.sourceRoot().toFile(), true);
-                ApplicationLayout srcAppLayout = initAppImageLayout.apply(
-                        appImage);
-                if (appImage.equals(PREDEFINED_RUNTIME_IMAGE.fetchFrom(params))) {
-                    // Application image points to run-time image.
-                    // Copy it.
-                    srcAppLayout.copy(thePackage.sourceApplicationLayout());
-                } else {
-                    // Application image is a newly created directory tree.
-                    // Move it.
-                    srcAppLayout.move(thePackage.sourceApplicationLayout());
-                    if (appImage.exists()) {
-                        // Empty app image directory might remain after all application
-                        // directories have been moved.
-                        appImage.delete();
-                    }
-                }
-            }
-
-            if (!StandardBundlerParam.isRuntimeInstaller(params)) {
-                desktopIntegration = new DesktopIntegration(thePackage, params);
-            } else {
-                desktopIntegration = null;
-            }
-
-            Map<String, String> data = createDefaultReplacementData(params);
-            if (desktopIntegration != null) {
-                data.putAll(desktopIntegration.create());
-            } else {
-                Stream.of(DESKTOP_COMMANDS_INSTALL, DESKTOP_COMMANDS_UNINSTALL,
-                        UTILITY_SCRIPTS).forEach(v -> data.put(v, ""));
-            }
-
-            data.putAll(createReplacementData(params));
-
-            File packageBundle = buildPackageBundle(Collections.unmodifiableMap(
-                    data), params, outputParentDir);
-
-            verifyOutputBundle(params, packageBundle.toPath()).stream()
-                    .filter(Objects::nonNull)
-                    .forEachOrdered(ex -> {
-                Log.verbose(ex.getLocalizedMessage());
-                Log.verbose(ex.getAdvice());
-            });
-
-            return packageBundle;
-        } catch (IOException ex) {
-            Log.verbose(ex);
-            throw new PackagerException(ex);
-        }
-    }
-
-    private List<String> getListOfNeededPackages(
-            Map<String, ? super Object> params) throws IOException {
-
-        PlatformPackage thePackage = createMetaPackage(params);
-
-        final List<String> xdgUtilsPackage;
-        if (desktopIntegration != null) {
-            xdgUtilsPackage = desktopIntegration.requiredPackages();
-        } else {
-            xdgUtilsPackage = Collections.emptyList();
-        }
-
-        final List<String> neededLibPackages;
-        if (withFindNeededPackages) {
-            LibProvidersLookup lookup = new LibProvidersLookup();
-            initLibProvidersLookup(params, lookup);
-
-            neededLibPackages = lookup.execute(thePackage.sourceRoot());
-        } else {
-            neededLibPackages = Collections.emptyList();
-        }
-
-        // Merge all package lists together.
-        // Filter out empty names, sort and remove duplicates.
-        List<String> result = Stream.of(xdgUtilsPackage, neededLibPackages).flatMap(
-                List::stream).filter(Predicate.not(String::isEmpty)).sorted().distinct().collect(
-                Collectors.toList());
-
-        Log.verbose(String.format("Required packages: %s", result));
-
-        return result;
-    }
-
-    private Map<String, String> createDefaultReplacementData(
-            Map<String, ? super Object> params) throws IOException {
-        Map<String, String> data = new HashMap<>();
-
-        data.put("APPLICATION_PACKAGE", createMetaPackage(params).name());
-        data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
-        data.put("APPLICATION_VERSION", VERSION.fetchFrom(params));
-        data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
-        data.put("APPLICATION_RELEASE", RELEASE.fetchFrom(params));
-
-        String defaultDeps = String.join(", ", getListOfNeededPackages(params));
-        String customDeps = LINUX_PACKAGE_DEPENDENCIES.fetchFrom(params).strip();
-        if (!customDeps.isEmpty() && !defaultDeps.isEmpty()) {
-            customDeps = ", " + customDeps;
-        }
-        data.put("PACKAGE_DEFAULT_DEPENDENCIES", defaultDeps);
-        data.put("PACKAGE_CUSTOM_DEPENDENCIES", customDeps);
-
-        return data;
-    }
-
-    abstract protected List<ConfigException> verifyOutputBundle(
-            Map<String, ? super Object> params, Path packageBundle);
-
-    abstract protected void initLibProvidersLookup(
-            Map<String, ? super Object> params,
-            LibProvidersLookup libProvidersLookup);
-
-    abstract protected List<ToolValidator> getToolValidators(
-            Map<String, ? super Object> params);
-
-    abstract protected void doValidate(Map<String, ? super Object> params)
-            throws ConfigException;
-
-    abstract protected Map<String, String> createReplacementData(
-            Map<String, ? super Object> params) throws IOException;
-
-    abstract protected File buildPackageBundle(
-            Map<String, String> replacementData,
-            Map<String, ? super Object> params, File outputParentDir) throws
-            PackagerException, IOException;
-
-    final protected PlatformPackage createMetaPackage(
-            Map<String, ? super Object> params) {
-        return new PlatformPackage() {
-            @Override
-            public String name() {
-                return packageName.fetchFrom(params);
-            }
-
-            @Override
-            public Path sourceRoot() {
-                return IMAGES_ROOT.fetchFrom(params).toPath().toAbsolutePath();
-            }
-
-            @Override
-            public ApplicationLayout sourceApplicationLayout() {
-                return appImageLayout(params).resolveAt(
-                        applicationInstallDir(sourceRoot()));
-            }
-
-            @Override
-            public ApplicationLayout installedApplicationLayout() {
-                return appImageLayout(params).resolveAt(
-                        applicationInstallDir(Path.of("/")));
-            }
-
-            private Path applicationInstallDir(Path root) {
-                Path installDir = Path.of(LINUX_INSTALL_DIR.fetchFrom(params),
-                        name());
-                if (installDir.isAbsolute()) {
-                    installDir = Path.of("." + installDir.toString()).normalize();
-                }
-                return root.resolve(installDir);
-            }
-        };
-    }
-
-    private ApplicationLayout appImageLayout(
-            Map<String, ? super Object> params) {
-        if (StandardBundlerParam.isRuntimeInstaller(params)) {
-            return ApplicationLayout.javaRuntime();
-        }
-        return ApplicationLayout.linuxAppImage();
-    }
-
-    private static void validateInstallDir(String installDir) throws
-            ConfigException {
-        if (installDir.startsWith("/usr/") || installDir.equals("/usr")) {
-            throw new ConfigException(MessageFormat.format(I18N.getString(
-                    "error.unsupported-install-dir"), installDir), null);
-        }
-
-        if (installDir.isEmpty()) {
-            throw new ConfigException(MessageFormat.format(I18N.getString(
-                    "error.invalid-install-dir"), "/"), null);
-        }
-
-        boolean valid = false;
-        try {
-            final Path installDirPath = Path.of(installDir);
-            valid = installDirPath.isAbsolute();
-            if (valid && !installDirPath.normalize().toString().equals(
-                    installDirPath.toString())) {
-                // Don't allow '/opt/foo/..' or /opt/.
-                valid = false;
-            }
-        } catch (InvalidPathException ex) {
-        }
-
-        if (!valid) {
-            throw new ConfigException(MessageFormat.format(I18N.getString(
-                    "error.invalid-install-dir"), installDir), null);
-        }
-    }
-
-    private static void validateFileAssociations(
-            List<Map<String, ? super Object>> associations) throws
-            ConfigException {
-        // only one mime type per association, at least one file extention
-        int assocIdx = 0;
-        for (var assoc : associations) {
-            ++assocIdx;
-            List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc);
-            if (mimes == null || mimes.isEmpty()) {
-                String msgKey = "error.no-content-types-for-file-association";
-                throw new ConfigException(
-                        MessageFormat.format(I18N.getString(msgKey), assocIdx),
-                        I18N.getString(msgKey + ".advise"));
-
-            }
-
-            if (mimes.size() > 1) {
-                String msgKey = "error.too-many-content-types-for-file-association";
-                throw new ConfigException(
-                        MessageFormat.format(I18N.getString(msgKey), assocIdx),
-                        I18N.getString(msgKey + ".advise"));
-            }
-        }
-    }
-
-    private final BundlerParamInfo<String> packageName;
-    private boolean withFindNeededPackages;
-    private DesktopIntegration desktopIntegration;
-
-    private static final BundlerParamInfo<LinuxAppBundler> APP_BUNDLER =
-        new StandardBundlerParam<>(
-                "linux.app.bundler",
-                LinuxAppBundler.class,
-                (params) -> new LinuxAppBundler(),
-                null
-        );
-
-}
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxRpmBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,323 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.*;
-import java.nio.file.Path;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-import static jdk.jpackage.internal.LinuxAppBundler.LINUX_INSTALL_DIR;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-
-/**
- * There are two command line options to configure license information for RPM
- * packaging: --linux-rpm-license-type and --license-file. Value of
- * --linux-rpm-license-type command line option configures "License:" section
- * of RPM spec. Value of --license-file command line option specifies a license
- * file to be added to the package. License file is a sort of documentation file
- * but it will be installed even if user selects an option to install the
- * package without documentation. --linux-rpm-license-type is the primary option
- * to set license information. --license-file makes little sense in case of RPM
- * packaging.
- */
-public class LinuxRpmBundler extends LinuxPackageBundler {
-
-    // Fedora rules for package naming are used here
-    // https://fedoraproject.org/wiki/Packaging:NamingGuidelines?rd=Packaging/NamingGuidelines
-    //
-    // all Fedora packages must be named using only the following ASCII
-    // characters. These characters are displayed here:
-    //
-    // abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._+
-    //
-    private static final Pattern RPM_PACKAGE_NAME_PATTERN =
-            Pattern.compile("[a-z\\d\\+\\-\\.\\_]+", Pattern.CASE_INSENSITIVE);
-
-    public static final BundlerParamInfo<String> PACKAGE_NAME =
-            new StandardBundlerParam<> (
-            Arguments.CLIOptions.LINUX_BUNDLE_NAME.getId(),
-            String.class,
-            params -> {
-                String nm = APP_NAME.fetchFrom(params);
-                if (nm == null) return null;
-
-                // make sure to lower case and spaces become dashes
-                nm = nm.toLowerCase().replaceAll("[ ]", "-");
-
-                return nm;
-            },
-            (s, p) -> {
-                if (!RPM_PACKAGE_NAME_PATTERN.matcher(s).matches()) {
-                    String msgKey = "error.invalid-value-for-package-name";
-                    throw new IllegalArgumentException(
-                            new ConfigException(MessageFormat.format(
-                                    I18N.getString(msgKey), s),
-                                    I18N.getString(msgKey + ".advice")));
-                }
-
-                return s;
-            }
-        );
-
-    public static final BundlerParamInfo<String> LICENSE_TYPE =
-        new StandardBundlerParam<>(
-                Arguments.CLIOptions.LINUX_RPM_LICENSE_TYPE.getId(),
-                String.class,
-                params -> I18N.getString("param.license-type.default"),
-                (s, p) -> s
-        );
-
-    public static final BundlerParamInfo<String> GROUP =
-            new StandardBundlerParam<>(
-            Arguments.CLIOptions.LINUX_CATEGORY.getId(),
-            String.class,
-            params -> null,
-            (s, p) -> s);
-
-    private final static String DEFAULT_SPEC_TEMPLATE = "template.spec";
-
-    public final static String TOOL_RPM = "rpm";
-    public final static String TOOL_RPMBUILD = "rpmbuild";
-    public final static DottedVersion TOOL_RPMBUILD_MIN_VERSION = DottedVersion.lazy(
-            "4.0");
-
-    public LinuxRpmBundler() {
-        super(PACKAGE_NAME);
-    }
-
-    @Override
-    public void doValidate(Map<String, ? super Object> params)
-            throws ConfigException {
-    }
-
-    private static ToolValidator createRpmbuildToolValidator() {
-        Pattern pattern = Pattern.compile(" (\\d+\\.\\d+)");
-        return new ToolValidator(TOOL_RPMBUILD).setMinimalVersion(
-                TOOL_RPMBUILD_MIN_VERSION).setVersionParser(lines -> {
-                    String versionString = lines.limit(1).collect(
-                            Collectors.toList()).get(0);
-                    Matcher matcher = pattern.matcher(versionString);
-                    if (matcher.find()) {
-                        return matcher.group(1);
-                    }
-                    return null;
-                });
-    }
-
-    @Override
-    protected List<ToolValidator> getToolValidators(
-            Map<String, ? super Object> params) {
-        return List.of(createRpmbuildToolValidator());
-    }
-
-    @Override
-    protected File buildPackageBundle(
-            Map<String, String> replacementData,
-            Map<String, ? super Object> params, File outputParentDir) throws
-            PackagerException, IOException {
-
-        Path specFile = specFile(params);
-
-        // prepare spec file
-        createResource(DEFAULT_SPEC_TEMPLATE, params)
-                .setCategory(I18N.getString("resource.rpm-spec-file"))
-                .setSubstitutionData(replacementData)
-                .saveToFile(specFile);
-
-        return buildRPM(params, outputParentDir.toPath()).toFile();
-    }
-
-    @Override
-    protected Map<String, String> createReplacementData(
-            Map<String, ? super Object> params) throws IOException {
-        Map<String, String> data = new HashMap<>();
-
-        data.put("APPLICATION_DIRECTORY", Path.of(LINUX_INSTALL_DIR.fetchFrom(
-                params), PACKAGE_NAME.fetchFrom(params)).toString());
-        data.put("APPLICATION_SUMMARY", APP_NAME.fetchFrom(params));
-        data.put("APPLICATION_LICENSE_TYPE", LICENSE_TYPE.fetchFrom(params));
-
-        String licenseFile = LICENSE_FILE.fetchFrom(params);
-        if (licenseFile != null) {
-            licenseFile = Path.of(licenseFile).toAbsolutePath().normalize().toString();
-        }
-        data.put("APPLICATION_LICENSE_FILE", licenseFile);
-        data.put("APPLICATION_GROUP", GROUP.fetchFrom(params));
-
-        return data;
-    }
-
-    @Override
-    protected void initLibProvidersLookup(
-            Map<String, ? super Object> params,
-            LibProvidersLookup libProvidersLookup) {
-        libProvidersLookup.setPackageLookup(file -> {
-            return Executor.of(TOOL_RPM,
-                "-q", "--queryformat", "%{name}\\n",
-                "-q", "--whatprovides", file.toString())
-                .saveOutput(true).executeExpectSuccess().getOutput().stream();
-        });
-    }
-
-    @Override
-    protected List<ConfigException> verifyOutputBundle(
-            Map<String, ? super Object> params, Path packageBundle) {
-        List<ConfigException> errors = new ArrayList<>();
-
-        String specFileName = specFile(params).getFileName().toString();
-
-        try {
-            List<PackageProperty> properties = List.of(
-                    new PackageProperty("Name", PACKAGE_NAME.fetchFrom(params),
-                            "APPLICATION_PACKAGE", specFileName),
-                    new PackageProperty("Version", VERSION.fetchFrom(params),
-                            "APPLICATION_VERSION", specFileName),
-                    new PackageProperty("Release", RELEASE.fetchFrom(params),
-                            "APPLICATION_RELEASE", specFileName),
-                    new PackageProperty("Arch", rpmArch(), null, specFileName));
-
-            List<String> actualValues = Executor.of(TOOL_RPM, "-qp", "--queryformat",
-                    properties.stream().map(entry -> String.format("%%{%s}",
-                    entry.name)).collect(Collectors.joining("\\n")),
-                    packageBundle.toString()).saveOutput(true).executeExpectSuccess().getOutput();
-
-            Iterator<String> actualValuesIt = actualValues.iterator();
-            properties.forEach(property -> errors.add(property.verifyValue(
-                    actualValuesIt.next())));
-        } catch (IOException ex) {
-            // Ignore error as it is not critical. Just report it.
-            Log.verbose(ex);
-        }
-
-        return errors;
-    }
-
-    /**
-     * Various ways to get rpm arch. Needed to address JDK-8233143. rpmbuild is
-     * mandatory for rpm packaging, try it first. rpm is optional and may not be
-     * available, use as the last resort.
-     */
-    private enum RpmArchReader {
-        Rpmbuild(TOOL_RPMBUILD, "--eval=%{_target_cpu}"),
-        Rpm(TOOL_RPM, "--eval=%{_target_cpu}");
-
-        RpmArchReader(String... cmdline) {
-            this.cmdline = cmdline;
-        }
-
-        String getRpmArch() throws IOException {
-            Executor exec = Executor.of(cmdline).saveOutput(true);
-            if (this == values()[values().length - 1]) {
-                exec.executeExpectSuccess();
-            } else if (exec.execute() != 0) {
-                return null;
-            }
-
-            return exec.getOutput().get(0);
-        }
-
-        private final String[] cmdline;
-    }
-
-    private String rpmArch() throws IOException {
-        if (rpmArch == null) {
-            for (var rpmArchReader : RpmArchReader.values()) {
-                rpmArch = rpmArchReader.getRpmArch();
-                if (rpmArch != null) {
-                    break;
-                }
-            }
-        }
-        return rpmArch;
-    }
-
-    private Path specFile(Map<String, ? super Object> params) {
-        return TEMP_ROOT.fetchFrom(params).toPath().resolve(Path.of("SPECS",
-                PACKAGE_NAME.fetchFrom(params) + ".spec"));
-    }
-
-    private Path buildRPM(Map<String, ? super Object> params,
-            Path outdir) throws IOException {
-
-        Path rpmFile = outdir.toAbsolutePath().resolve(String.format(
-                "%s-%s-%s.%s.rpm", PACKAGE_NAME.fetchFrom(params),
-                VERSION.fetchFrom(params), RELEASE.fetchFrom(params), rpmArch()));
-
-        Log.verbose(MessageFormat.format(I18N.getString(
-                "message.outputting-bundle-location"),
-                rpmFile.getParent()));
-
-        PlatformPackage thePackage = createMetaPackage(params);
-
-        //run rpmbuild
-        Executor.of(
-                TOOL_RPMBUILD,
-                "-bb", specFile(params).toAbsolutePath().toString(),
-                "--define", String.format("%%_sourcedir %s",
-                        thePackage.sourceRoot()),
-                // save result to output dir
-                "--define", String.format("%%_rpmdir %s", rpmFile.getParent()),
-                // do not use other system directories to build as current user
-                "--define", String.format("%%_topdir %s",
-                        TEMP_ROOT.fetchFrom(params).toPath().toAbsolutePath()),
-                "--define", String.format("%%_rpmfilename %s", rpmFile.getFileName())
-        ).executeExpectSuccess();
-
-        Log.verbose(MessageFormat.format(
-                I18N.getString("message.output-bundle-location"),
-                rpmFile.getParent()));
-
-        return rpmFile;
-    }
-
-    @Override
-    public String getName() {
-        return I18N.getString("rpm.bundler.name");
-    }
-
-    @Override
-    public String getID() {
-        return "rpm";
-    }
-
-    @Override
-    public boolean supported(boolean runtimeInstaller) {
-        return Platform.isLinux() && (createRpmbuildToolValidator().validate() == null);
-    }
-
-    @Override
-    public boolean isDefault() {
-        return !LinuxDebBundler.isDebian();
-    }
-
-    private String rpmArch;
-}
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/PackageProperty.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2019, 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.text.MessageFormat;
-
-final class PackageProperty {
-    /**
-     * Constructor
-     *
-     * @param name property name
-     * @param expectedValue expected property value
-     * @param substString substitution string to be placed in resource file to
-     * be replaced with the expected property value by jpackage at package build
-     * time
-     * @param customResource name of custom resource from resource directory in
-     * which this package property can be set
-     */
-    PackageProperty(String name, String expectedValue, String substString,
-            String customResource) {
-        this.name = name;
-        this.expectedValue = expectedValue;
-        this.substString = substString;
-        this.customResource = customResource;
-    }
-    
-    ConfigException verifyValue(String actualValue) {
-        if (expectedValue.equals(actualValue)) {
-            return null;
-        }
-        
-        final String advice;
-        if (substString != null) {
-            advice = MessageFormat.format(I18N.getString(
-                    "error.unexpected-package-property.advice"), substString,
-                    actualValue, name, customResource);
-        } else {
-            advice = MessageFormat.format(I18N.getString(
-                    "error.unexpected-default-package-property.advice"), name,
-                    customResource);
-        }
-        
-        return new ConfigException(MessageFormat.format(I18N.getString(
-                "error.unexpected-package-property"), name,
-                expectedValue, actualValue, customResource, substString), advice);
-    }
-
-    final String name;
-    private final String expectedValue;
-    private final String substString;
-    private final String customResource;
-}
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-app.bundler.name=Linux Application Image
-deb.bundler.name=DEB Bundle
-rpm.bundler.name=RPM Bundle
-
-param.license-type.default=Unknown
-param.menu-group.default=Unknown
-
-resource.deb-control-file=DEB control file
-resource.deb-preinstall-script=DEB preinstall script
-resource.deb-prerm-script=DEB prerm script
-resource.deb-postinstall-script=DEB postinstall script
-resource.deb-postrm-script=DEB postrm script
-resource.copyright-file=Copyright file
-resource.menu-shortcut-descriptor=Menu shortcut descriptor
-resource.menu-icon=menu icon
-resource.rpm-spec-file=RPM spec file
-
-error.tool-not-found.advice=Please install required packages
-error.tool-old-version.advice=Please install required packages
-
-error.invalid-install-dir=Invalid installation directory "{0}"
-error.unsupported-install-dir=Installing to system directory "{0}" is currently unsupported
-
-error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}
-error.too-many-content-types-for-file-association=More than one MIME types was specified for File Association number {0}.
-error.invalid-value-for-package-name=Invalid value "{0}" for the bundle name.
-error.invalid-value-for-package-name.advice=Set the "linux-bundle-name" option to a valid Debian package name. Note that the package names must consist only of lower case letters (a-z), digits (0-9), plus (+) and minus (-) signs, and periods (.). They must be at least two characters long and must start with an alphanumeric character.
-
-message.icon-not-png=The specified icon "{0}" is not a PNG file and will not be used. The default icon will be used in it's place.
-message.test-for-tool=Test for [{0}]. Result: {1}
-message.outputting-to-location=Generating DEB for installer to: {0}.
-message.output-to-location=Package (.deb) saved to: {0}.
-message.debs-like-licenses=Debian packages should specify a license. The absence of a license will cause some linux distributions to complain about the quality of the application.
-message.outputting-bundle-location=Generating RPM for installer to: {0}.
-message.output-bundle-location=Package (.rpm) saved to: {0}.
-message.creating-association-with-null-extension=Creating association with null extension.
-
-message.ldd-not-available=ldd command not found. Package dependencies will not be generated.
-message.deb-ldd-not-available.advice=Install "libc-bin" DEB package to get ldd.
-message.rpm-ldd-not-available.advice=Install "glibc-common" RPM package to get ldd.
-
-error.unexpected-package-property=Expected value of "{0}" property is [{1}]. Actual value in output package is [{2}]. Looks like custom "{3}" file from resource directory contained hard coded value of "{0}" property
-error.unexpected-package-property.advice=Use [{0}] pattern string instead of hard coded value [{1}] of {2} property in custom "{3}" file
-error.unexpected-default-package-property.advice=Don't explicitly set value of {0} property in custom "{1}" file
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-app.bundler.name=Linux Application Image
-deb.bundler.name=DEB Bundle
-rpm.bundler.name=RPM Bundle
-
-param.license-type.default=Unknown
-param.menu-group.default=Unknown
-
-resource.deb-control-file=DEB control file
-resource.deb-preinstall-script=DEB preinstall script
-resource.deb-prerm-script=DEB prerm script
-resource.deb-postinstall-script=DEB postinstall script
-resource.deb-postrm-script=DEB postrm script
-resource.copyright-file=Copyright file
-resource.menu-shortcut-descriptor=Menu shortcut descriptor
-resource.menu-icon=menu icon
-resource.rpm-spec-file=RPM spec file
-
-error.tool-not-found.advice=Please install required packages
-error.tool-old-version.advice=Please install required packages
-
-error.invalid-install-dir=Invalid installation directory "{0}"
-error.unsupported-install-dir=Installing to system directory "{0}" is currently unsupported
-
-error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}
-error.too-many-content-types-for-file-association=More than one MIME types was specified for File Association number {0}.
-error.invalid-value-for-package-name=Invalid value "{0}" for the bundle name.
-error.invalid-value-for-package-name.advice=Set the "linux-bundle-name" option to a valid Debian package name. Note that the package names must consist only of lower case letters (a-z), digits (0-9), plus (+) and minus (-) signs, and periods (.). They must be at least two characters long and must start with an alphanumeric character.
-
-message.icon-not-png=The specified icon "{0}" is not a PNG file and will not be used. The default icon will be used in it's place.
-message.test-for-tool=Test for [{0}]. Result: {1}
-message.outputting-to-location=Generating DEB for installer to: {0}.
-message.output-to-location=Package (.deb) saved to: {0}.
-message.debs-like-licenses=Debian packages should specify a license. The absence of a license will cause some linux distributions to complain about the quality of the application.
-message.outputting-bundle-location=Generating RPM for installer to: {0}.
-message.output-bundle-location=Package (.rpm) saved to: {0}.
-message.creating-association-with-null-extension=Creating association with null extension.
-
-message.ldd-not-available=ldd command not found. Package dependencies will not be generated.
-message.deb-ldd-not-available.advice=Install "libc-bin" DEB package to get ldd.
-message.rpm-ldd-not-available.advice=Install "glibc-common" RPM package to get ldd.
-
-error.unexpected-package-property=Expected value of "{0}" property is [{1}]. Actual value in output package is [{2}]. Looks like custom "{3}" file from resource directory contained hard coded value of "{0}" property
-error.unexpected-package-property.advice=Use [{0}] pattern string instead of hard coded value [{1}] of {2} property in custom "{3}" file
-error.unexpected-default-package-property.advice=Don't explicitly set value of {0} property in custom "{1}" file
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-app.bundler.name=Linux Application Image
-deb.bundler.name=DEB Bundle
-rpm.bundler.name=RPM Bundle
-
-param.license-type.default=Unknown
-param.menu-group.default=Unknown
-
-resource.deb-control-file=DEB control file
-resource.deb-preinstall-script=DEB preinstall script
-resource.deb-prerm-script=DEB prerm script
-resource.deb-postinstall-script=DEB postinstall script
-resource.deb-postrm-script=DEB postrm script
-resource.copyright-file=Copyright file
-resource.menu-shortcut-descriptor=Menu shortcut descriptor
-resource.menu-icon=menu icon
-resource.rpm-spec-file=RPM spec file
-
-error.tool-not-found.advice=Please install required packages
-error.tool-old-version.advice=Please install required packages
-
-error.invalid-install-dir=Invalid installation directory "{0}"
-error.unsupported-install-dir=Installing to system directory "{0}" is currently unsupported
-
-error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}
-error.too-many-content-types-for-file-association=More than one MIME types was specified for File Association number {0}.
-error.invalid-value-for-package-name=Invalid value "{0}" for the bundle name.
-error.invalid-value-for-package-name.advice=Set the "linux-bundle-name" option to a valid Debian package name. Note that the package names must consist only of lower case letters (a-z), digits (0-9), plus (+) and minus (-) signs, and periods (.). They must be at least two characters long and must start with an alphanumeric character.
-
-message.icon-not-png=The specified icon "{0}" is not a PNG file and will not be used. The default icon will be used in it's place.
-message.test-for-tool=Test for [{0}]. Result: {1}
-message.outputting-to-location=Generating DEB for installer to: {0}.
-message.output-to-location=Package (.deb) saved to: {0}.
-message.debs-like-licenses=Debian packages should specify a license. The absence of a license will cause some linux distributions to complain about the quality of the application.
-message.outputting-bundle-location=Generating RPM for installer to: {0}.
-message.output-bundle-location=Package (.rpm) saved to: {0}.
-message.creating-association-with-null-extension=Creating association with null extension.
-
-message.ldd-not-available=ldd command not found. Package dependencies will not be generated.
-message.deb-ldd-not-available.advice=Install "libc-bin" DEB package to get ldd.
-message.rpm-ldd-not-available.advice=Install "glibc-common" RPM package to get ldd.
-
-error.unexpected-package-property=Expected value of "{0}" property is [{1}]. Actual value in output package is [{2}]. Looks like custom "{3}" file from resource directory contained hard coded value of "{0}" property
-error.unexpected-package-property.advice=Use [{0}] pattern string instead of hard coded value [{1}] of {2} property in custom "{3}" file
-error.unexpected-default-package-property.advice=Don't explicitly set value of {0} property in custom "{1}" file
Binary file src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/java32.png has changed
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.control	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-Package: APPLICATION_PACKAGE
-Version: APPLICATION_VERSION-APPLICATION_RELEASE
-Section: APPLICATION_SECTION
-Maintainer: APPLICATION_MAINTAINER
-Priority: optional
-Architecture: APPLICATION_ARCH
-Provides: APPLICATION_PACKAGE
-Description: APPLICATION_DESCRIPTION
-Depends: PACKAGE_DEFAULT_DEPENDENCIES PACKAGE_CUSTOM_DEPENDENCIES
-Installed-Size: APPLICATION_INSTALLED_SIZE
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.copyright	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-
-Files: *
-Copyright: APPLICATION_COPYRIGHT
-License: APPLICATION_LICENSE_TEXT
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.desktop	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-[Desktop Entry]
-Name=APPLICATION_NAME
-Comment=APPLICATION_DESCRIPTION
-Exec=APPLICATION_LAUNCHER
-Icon=APPLICATION_ICON
-Terminal=false
-Type=Application
-Categories=DEPLOY_BUNDLE_CATEGORY
-DESKTOP_MIMES
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.postinst	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#!/bin/sh
-# postinst script for APPLICATION_PACKAGE
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-#        * <postinst> `configure' <most-recently-configured-version>
-#        * <old-postinst> `abort-upgrade' <new version>
-#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
-#          <new-version>
-#        * <postinst> `abort-remove'
-#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
-#          <failed-install-package> <version> `removing'
-#          <conflicting-package> <version>
-# for details, see https://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-case "$1" in
-    configure)
-DESKTOP_COMMANDS_INSTALL
-    ;;
-
-    abort-upgrade|abort-remove|abort-deconfigure)
-    ;;
-
-    *)
-        echo "postinst called with unknown argument \`$1'" >&2
-        exit 1
-    ;;
-esac
-
-exit 0
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.postrm	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-#!/bin/sh
-# postrm script for APPLICATION_PACKAGE
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-#        * <postrm> `remove'
-#        * <postrm> `purge'
-#        * <old-postrm> `upgrade' <new-version>
-#        * <new-postrm> `failed-upgrade' <old-version>
-#        * <new-postrm> `abort-install'
-#        * <new-postrm> `abort-install' <old-version>
-#        * <new-postrm> `abort-upgrade' <old-version>
-#        * <disappearer's-postrm> `disappear' <overwriter>
-#          <overwriter-version>
-# for details, see https://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-case "$1" in
-    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
-    ;;
-
-    *)
-        echo "postrm called with unknown argument \`$1'" >&2
-        exit 1
-    ;;
-esac
-
-exit 0
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.preinst	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#!/bin/sh
-# preinst script for APPLICATION_PACKAGE
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-#        * <new-preinst> `install'
-#        * <new-preinst> `install' <old-version>
-#        * <new-preinst> `upgrade' <old-version>
-#        * <old-preinst> `abort-upgrade' <new-version>
-# for details, see https://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-
-case "$1" in
-    install|upgrade)
-    ;;
-
-    abort-upgrade)
-    ;;
-
-    *)
-        echo "preinst called with unknown argument \`$1'" >&2
-        exit 1
-    ;;
-esac
-
-exit 0
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.prerm	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-#!/bin/sh
-# prerm script for APPLICATION_PACKAGE
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-#        * <prerm> `remove'
-#        * <old-prerm> `upgrade' <new-version>
-#        * <new-prerm> `failed-upgrade' <old-version>
-#        * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
-#        * <deconfigured's-prerm> `deconfigure' `in-favour'
-#          <package-being-installed> <version> `removing'
-#          <conflicting-package> <version>
-# for details, see https://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-
-UTILITY_SCRIPTS
-
-case "$1" in
-    remove|upgrade|deconfigure)
-DESKTOP_COMMANDS_UNINSTALL
-    ;;
-
-    failed-upgrade)
-    ;;
-
-    *)
-        echo "prerm called with unknown argument \`$1'" >&2
-        exit 1
-    ;;
-esac
-
-exit 0
-
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/template.spec	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-Summary: APPLICATION_SUMMARY
-Name: APPLICATION_PACKAGE
-Version: APPLICATION_VERSION
-Release: APPLICATION_RELEASE
-License: APPLICATION_LICENSE_TYPE
-Vendor: APPLICATION_VENDOR
-Prefix: %{dirname:APPLICATION_DIRECTORY}
-Provides: APPLICATION_PACKAGE
-%if "xAPPLICATION_GROUP" != x
-Group: APPLICATION_GROUP
-%endif
-
-Autoprov: 0
-Autoreq: 0
-%if "xPACKAGE_DEFAULT_DEPENDENCIES" != x || "xPACKAGE_CUSTOM_DEPENDENCIES" != x
-Requires: PACKAGE_DEFAULT_DEPENDENCIES PACKAGE_CUSTOM_DEPENDENCIES
-%endif
-
-#comment line below to enable effective jar compression
-#it could easily get your package size from 40 to 15Mb but
-#build time will substantially increase and it may require unpack200/system java to install
-%define __jar_repack %{nil}
-
-%description
-APPLICATION_DESCRIPTION
-
-%prep
-
-%build
-
-%install
-rm -rf %{buildroot}
-install -d -m 755 %{buildroot}APPLICATION_DIRECTORY
-cp -r %{_sourcedir}APPLICATION_DIRECTORY/* %{buildroot}APPLICATION_DIRECTORY
-%if "xAPPLICATION_LICENSE_FILE" != x
-  %define license_install_file %{_defaultlicensedir}/%{name}-%{version}/%{basename:APPLICATION_LICENSE_FILE}
-  install -d -m 755 %{buildroot}%{dirname:%{license_install_file}}
-  install -m 644 APPLICATION_LICENSE_FILE %{buildroot}%{license_install_file}
-%endif
-
-%files
-%if "xAPPLICATION_LICENSE_FILE" != x
-  %license %{license_install_file}
-  %{dirname:%{license_install_file}}
-%endif
-# If installation directory for the application is /a/b/c, we want only root
-# component of the path (/a) in the spec file to make sure all subdirectories
-# are owned by the package.
-%(echo APPLICATION_DIRECTORY | sed -e "s|\(^/[^/]\{1,\}\).*$|\1|")
-
-%post
-DESKTOP_COMMANDS_INSTALL
-
-%preun
-UTILITY_SCRIPTS
-DESKTOP_COMMANDS_UNINSTALL
-
-%clean
--- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/utils.sh	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-#
-# Remove $1 desktop file from the list of default handlers for $2 mime type
-# in $3 file dumping output to stdout.
-#
-_filter_out_default_mime_handler ()
-{
-  local defaults_list="$3"
-
-  local desktop_file="$1"
-  local mime_type="$2"
-
-  awk -f- "$defaults_list" <<EOF
-  BEGIN {
-    mime_type="$mime_type"
-    mime_type_regexp="~" mime_type "="
-    desktop_file="$desktop_file"
-  }
-  \$0 ~ mime_type {
-    \$0 = substr(\$0, length(mime_type) + 2);
-    split(\$0, desktop_files, ";")
-    remaining_desktop_files
-    counter=0
-    for (idx in desktop_files) {
-      if (desktop_files[idx] != desktop_file) {
-        ++counter;
-      }
-    }
-    if (counter) {
-      printf mime_type "="
-      for (idx in desktop_files) {
-        if (desktop_files[idx] != desktop_file) {
-          printf desktop_files[idx]
-          if (--counter) {
-            printf ";"
-          }
-        }
-      }
-      printf "\n"
-    }
-    next
-  }
-
-  { print }
-EOF
-}
-
-
-#
-# Remove $2 desktop file from the list of default handlers for $@ mime types
-# in $1 file.
-# Result is saved in $1 file.
-#
-_uninstall_default_mime_handler ()
-{
-  local defaults_list=$1
-  shift
-  [ -f "$defaults_list" ] || return 0
-
-  local desktop_file="$1"
-  shift
-
-  tmpfile1=$(mktemp)
-  tmpfile2=$(mktemp)
-  cat "$defaults_list" > "$tmpfile1"
-
-  local v
-  local update=
-  for mime in "$@"; do
-    _filter_out_default_mime_handler "$desktop_file" "$mime" "$tmpfile1" > "$tmpfile2"
-    v="$tmpfile2"
-    tmpfile2="$tmpfile1"
-    tmpfile1="$v"
-
-    if ! diff -q "$tmpfile1" "$tmpfile2" > /dev/null; then
-      update=yes
-      trace Remove $desktop_file default handler for $mime mime type from $defaults_list file
-    fi
-  done
-
-  if [ -n "$update" ]; then
-    cat "$tmpfile1" > "$defaults_list"
-    trace "$defaults_list" file updated
-  fi
-
-  rm -f "$tmpfile1" "$tmpfile2"
-}
-
-
-#
-# Remove $1 desktop file from the list of default handlers for $@ mime types
-# in all known system defaults lists.
-#
-uninstall_default_mime_handler ()
-{
-  for f in /usr/share/applications/defaults.list /usr/local/share/applications/defaults.list; do
-    _uninstall_default_mime_handler "$f" "$@"
-  done
-}
-
-
-trace ()
-{
-  echo "$@"
-}
--- a/src/jdk.jpackage/linux/classes/module-info.java.extra	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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.
- */
-
-provides jdk.jpackage.internal.Bundler with
-    jdk.jpackage.internal.LinuxAppBundler,
-    jdk.jpackage.internal.LinuxDebBundler,
-    jdk.jpackage.internal.LinuxRpmBundler;
-
--- a/src/jdk.jpackage/linux/native/jpackageapplauncher/launcher.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include <dlfcn.h>
-#include <locale.h>
-#include <string>
-#include <libgen.h>
-#include <stdio.h>
-#include <unistd.h>
-
-
-typedef bool (*start_launcher)(int argc, char* argv[]);
-typedef void (*stop_launcher)();
-
-#define MAX_PATH 1024
-
-std::string GetProgramPath() {
-    ssize_t len = 0;
-    std::string result;
-    char buffer[MAX_PATH] = {0};
-
-    if ((len = readlink("/proc/self/exe", buffer, MAX_PATH - 1)) != -1) {
-        buffer[len] = '\0';
-        result = buffer;
-    }
-
-    return result;
-}
-
-int main(int argc, char *argv[]) {
-    int result = 1;
-    setlocale(LC_ALL, "en_US.utf8");
-    void* library = NULL;
-
-    {
-        std::string programPath = GetProgramPath();
-        std::string libraryName = dirname((char*)programPath.c_str());
-        libraryName += "/../lib/libapplauncher.so";
-        library = dlopen(libraryName.c_str(), RTLD_LAZY);
-
-        if (library == NULL) {
-            fprintf(stderr, "dlopen failed: %s\n", dlerror());
-            fprintf(stderr, "%s not found.\n", libraryName.c_str());
-        }
-    }
-
-    if (library != NULL) {
-        start_launcher start = (start_launcher)dlsym(library, "start_launcher");
-        stop_launcher stop = (stop_launcher)dlsym(library, "stop_launcher");
-
-        if (start != NULL && stop != NULL) {
-            if (start(argc, argv) == true) {
-                result = 0;
-                stop();
-            }
-        } else {
-            fprintf(stderr, "cannot find start_launcher and stop_launcher in libapplauncher.so");
-        }
-
-        dlclose(library);
-    }
-
-
-    return result;
-}
--- a/src/jdk.jpackage/linux/native/libapplauncher/LinuxPlatform.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1080 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "Platform.h"
-
-#include "JavaVirtualMachine.h"
-#include "LinuxPlatform.h"
-#include "PlatformString.h"
-#include "IniFile.h"
-#include "Helpers.h"
-#include "FilePath.h"
-
-#include <stdlib.h>
-#include <pwd.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <limits.h>
-#include <signal.h>
-
-#define LINUX_JPACKAGE_TMP_DIR "/.java/jpackage/tmp"
-
-TString GetEnv(const TString &name) {
-    TString result;
-
-    char *value = ::getenv((TCHAR*) name.c_str());
-
-    if (value != NULL) {
-        result = value;
-    }
-
-    return result;
-}
-
-LinuxPlatform::LinuxPlatform(void) : Platform(),
-PosixPlatform() {
-    FMainThread = pthread_self();
-}
-
-LinuxPlatform::~LinuxPlatform(void) {
-}
-
-TString LinuxPlatform::GetPackageAppDirectory() {
-    return FilePath::IncludeTrailingSeparator(
-            GetPackageRootDirectory()) + _T("lib/app");
-}
-
-TString LinuxPlatform::GetAppName() {
-    TString result = GetModuleFileName();
-    result = FilePath::ExtractFileName(result);
-    return result;
-}
-
-TString LinuxPlatform::GetPackageLauncherDirectory() {
-    return FilePath::IncludeTrailingSeparator(
-            GetPackageRootDirectory()) + _T("bin");
-}
-
-TString LinuxPlatform::GetPackageRuntimeBinDirectory() {
-    return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory())
-            + _T("runtime/bin");
-}
-
-void LinuxPlatform::ShowMessage(TString title, TString description) {
-    printf("%s %s\n", PlatformString(title).toPlatformString(),
-            PlatformString(description).toPlatformString());
-    fflush(stdout);
-}
-
-void LinuxPlatform::ShowMessage(TString description) {
-    TString appname = GetModuleFileName();
-    appname = FilePath::ExtractFileName(appname);
-    ShowMessage(PlatformString(appname).toPlatformString(),
-            PlatformString(description).toPlatformString());
-}
-
-TCHAR* LinuxPlatform::ConvertStringToFileSystemString(TCHAR* Source,
-        bool &release) {
-    // Not Implemented.
-    return NULL;
-}
-
-TCHAR* LinuxPlatform::ConvertFileSystemStringToString(TCHAR* Source,
-        bool &release) {
-    // Not Implemented.
-    return NULL;
-}
-
-TString LinuxPlatform::GetModuleFileName() {
-    ssize_t len = 0;
-    TString result;
-    DynamicBuffer<TCHAR> buffer(MAX_PATH);
-    if (buffer.GetData() == NULL) {
-        return result;
-    }
-
-    if ((len = readlink("/proc/self/exe", buffer.GetData(),
-            MAX_PATH - 1)) != -1) {
-        buffer[len] = '\0';
-        result = buffer.GetData();
-    }
-
-    return result;
-}
-
-TString LinuxPlatform::GetPackageRootDirectory() {
-    TString result;
-    TString filename = GetModuleFileName();
-    TString binPath = FilePath::ExtractFilePath(filename);
-
-    size_t slash = binPath.find_last_of(TRAILING_PATHSEPARATOR);
-    if (slash != TString::npos) {
-        result = binPath.substr(0, slash);
-    }
-
-    return result;
-}
-
-TString LinuxPlatform::GetAppDataDirectory() {
-    TString result;
-    TString home = GetEnv(_T("HOME"));
-
-    if (home.empty() == false) {
-        result += FilePath::IncludeTrailingSeparator(home) + _T(".local");
-    }
-
-    return result;
-}
-
-ISectionalPropertyContainer* LinuxPlatform::GetConfigFile(TString FileName) {
-    IniFile *result = new IniFile();
-    if (result == NULL) {
-        return NULL;
-    }
-
-    result->LoadFromFile(FileName);
-
-    return result;
-}
-
-TString LinuxPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) {
-    TString result = FilePath::IncludeTrailingSeparator(RuntimePath) +
-            "lib/libjli.so";
-
-    if (FilePath::FileExists(result) == false) {
-        result = FilePath::IncludeTrailingSeparator(RuntimePath) +
-                "lib/jli/libjli.so";
-        if (FilePath::FileExists(result) == false) {
-            printf("Cannot find libjli.so!");
-        }
-    }
-
-    return result;
-}
-
-bool LinuxPlatform::IsMainThread() {
-    bool result = (FMainThread == pthread_self());
-    return result;
-}
-
-TString LinuxPlatform::getTmpDirString() {
-    return TString(LINUX_JPACKAGE_TMP_DIR);
-}
-
-TPlatformNumber LinuxPlatform::GetMemorySize() {
-    long pages = sysconf(_SC_PHYS_PAGES);
-    long page_size = sysconf(_SC_PAGE_SIZE);
-    TPlatformNumber result = pages * page_size;
-    result = result / 1048576; // Convert from bytes to megabytes.
-    return result;
-}
-
-void PosixProcess::Cleanup() {
-    if (FOutputHandle != 0) {
-        close(FOutputHandle);
-        FOutputHandle = 0;
-    }
-
-    if (FInputHandle != 0) {
-        close(FInputHandle);
-        FInputHandle = 0;
-    }
-}
-
-#define PIPE_READ 0
-#define PIPE_WRITE 1
-
-bool PosixProcess::Execute(const TString Application,
-        const std::vector<TString> Arguments, bool AWait) {
-    bool result = false;
-
-    if (FRunning == false) {
-        FRunning = true;
-
-        int handles[2];
-
-        if (pipe(handles) == -1) {
-            return false;
-        }
-
-        struct sigaction sa;
-        sa.sa_handler = SIG_IGN;
-        sigemptyset(&sa.sa_mask);
-        sa.sa_flags = 0;
-
-        FChildPID = fork();
-
-        // PID returned by vfork is 0 for the child process and the
-        // PID of the child process for the parent.
-        if (FChildPID == -1) {
-            // Error
-            TString message = PlatformString::Format(
-                    _T("Error: Unable to create process %s"),
-                    Application.data());
-            throw Exception(message);
-        } else if (FChildPID == 0) {
-            Cleanup();
-            TString command = Application;
-
-            for (std::vector<TString>::const_iterator iterator =
-                    Arguments.begin(); iterator != Arguments.end();
-                    iterator++) {
-                command += TString(_T(" ")) + *iterator;
-            }
-#ifdef DEBUG
-            printf("%s\n", command.data());
-#endif // DEBUG
-
-            dup2(handles[PIPE_READ], STDIN_FILENO);
-            dup2(handles[PIPE_WRITE], STDOUT_FILENO);
-
-            close(handles[PIPE_READ]);
-            close(handles[PIPE_WRITE]);
-
-            execl("/bin/sh", "sh", "-c", command.data(), (char *) 0);
-
-            _exit(127);
-        } else {
-            FOutputHandle = handles[PIPE_READ];
-            FInputHandle = handles[PIPE_WRITE];
-
-            if (AWait == true) {
-                ReadOutput();
-                Wait();
-                Cleanup();
-                FRunning = false;
-                result = true;
-            } else {
-                result = true;
-            }
-        }
-    }
-
-    return result;
-}
-
-
-//----------------------------------------------------------------------------
-
-#ifndef __UNIX_JPACKAGE_PLATFORM__
-#define __UNIX_JPACKAGE_PLATFORM__
-
-/** Provide an abstraction for difference in the platform APIs,
-     e.g. string manipulation functions, etc. */
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/stat.h>
-
-#define TCHAR char
-
-#define _T(x) x
-
-#define JPACKAGE_MULTIBYTE_SNPRINTF snprintf
-
-#define JPACKAGE_SNPRINTF(buffer, sizeOfBuffer, count, format, ...) \
-    snprintf((buffer), (count), (format), __VA_ARGS__)
-
-#define JPACKAGE_PRINTF(format, ...) \
-    printf((format), ##__VA_ARGS__)
-
-#define JPACKAGE_FPRINTF(dest, format, ...) \
-    fprintf((dest), (format), __VA_ARGS__)
-
-#define JPACKAGE_SSCANF(buf, format, ...) \
-    sscanf((buf), (format), __VA_ARGS__)
-
-#define JPACKAGE_STRDUP(strSource) \
-    strdup((strSource))
-
-//return "error code" (like on Windows)
-
-static int JPACKAGE_STRNCPY(char *strDest, size_t numberOfElements,
-        const char *strSource, size_t count) {
-    char *s = strncpy(strDest, strSource, count);
-    // Duplicate behavior of the Windows' _tcsncpy_s() by adding a NULL
-    // terminator at the end of the string.
-    if (count < numberOfElements) {
-        s[count] = '\0';
-    } else {
-        s[numberOfElements - 1] = '\0';
-    }
-    return (s == strDest) ? 0 : 1;
-}
-
-#define JPACKAGE_STRICMP(x, y) \
-    strcasecmp((x), (y))
-
-#define JPACKAGE_STRNICMP(x, y, cnt) \
-    strncasecmp((x), (y), (cnt))
-
-#define JPACKAGE_STRNCMP(x, y, cnt) \
-    strncmp((x), (y), (cnt))
-
-#define JPACKAGE_STRLEN(x) \
-    strlen((x))
-
-#define JPACKAGE_STRSTR(x, y) \
-    strstr((x), (y))
-
-#define JPACKAGE_STRCHR(x, y) \
-    strchr((x), (y))
-
-#define JPACKAGE_STRRCHR(x, y) \
-    strrchr((x), (y))
-
-#define JPACKAGE_STRPBRK(x, y) \
-    strpbrk((x), (y))
-
-#define JPACKAGE_GETENV(x) \
-    getenv((x))
-
-#define JPACKAGE_PUTENV(x) \
-    putenv((x))
-
-#define JPACKAGE_STRCMP(x, y) \
-    strcmp((x), (y))
-
-#define JPACKAGE_STRCPY(x, y) \
-    strcpy((x), (y))
-
-#define JPACKAGE_STRCAT(x, y) \
-    strcat((x), (y))
-
-#define JPACKAGE_ATOI(x) \
-    atoi((x))
-
-#define JPACKAGE_FOPEN(x, y) \
-    fopen((x), (y))
-
-#define JPACKAGE_FGETS(x, y, z) \
-    fgets((x), (y), (z))
-
-#define JPACKAGE_REMOVE(x) \
-    remove((x))
-
-#define JPACKAGE_SPAWNV(mode, cmd, args) \
-    spawnv((mode), (cmd), (args))
-
-#define JPACKAGE_ISDIGIT(ch) isdigit(ch)
-
-// for non-unicode, just return the input string for
-// the following 2 conversions
-#define JPACKAGE_NEW_MULTIBYTE(message) message
-
-#define JPACKAGE_NEW_FROM_MULTIBYTE(message) message
-
-// for non-unicode, no-op for the relase operation
-// since there is no memory allocated for the
-// string conversions
-#define JPACKAGE_RELEASE_MULTIBYTE(tmpMBCS)
-
-#define JPACKAGE_RELEASE_FROM_MULTIBYTE(tmpMBCS)
-
-// The size will be used for converting from 1 byte to 1 byte encoding.
-// Ensure have space for zero-terminator.
-#define JPACKAGE_GET_SIZE_FOR_ENCODING(message, theLength) (theLength + 1)
-
-#endif
-#define xmlTagType    0
-#define xmlPCDataType 1
-
-typedef struct _xmlNode XMLNode;
-typedef struct _xmlAttribute XMLAttribute;
-
-struct _xmlNode {
-    int _type; // Type of node: tag, pcdata, cdate
-    TCHAR* _name; // Contents of node
-    XMLNode* _next; // Next node at same level
-    XMLNode* _sub; // First sub-node
-    XMLAttribute* _attributes; // List of attributes
-};
-
-struct _xmlAttribute {
-    TCHAR* _name; // Name of attribute
-    TCHAR* _value; // Value of attribute
-    XMLAttribute* _next; // Next attribute for this tag
-};
-
-// Public interface
-static void RemoveNonAsciiUTF8FromBuffer(char *buf);
-XMLNode* ParseXMLDocument(TCHAR* buf);
-void FreeXMLDocument(XMLNode* root);
-
-// Utility methods for parsing document
-XMLNode* FindXMLChild(XMLNode* root, const TCHAR* name);
-TCHAR* FindXMLAttribute(XMLAttribute* attr, const TCHAR* name);
-
-// Debugging
-void PrintXMLDocument(XMLNode* node, int indt);
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <setjmp.h>
-#include <stdlib.h>
-#include <wctype.h>
-
-#define JWS_assert(s, msg)      \
-    if (!(s)) { Abort(msg); }
-
-
-// Internal declarations
-static XMLNode* ParseXMLElement(void);
-static XMLAttribute* ParseXMLAttribute(void);
-static TCHAR* SkipWhiteSpace(TCHAR *p);
-static TCHAR* SkipXMLName(TCHAR *p);
-static TCHAR* SkipXMLComment(TCHAR *p);
-static TCHAR* SkipXMLDocType(TCHAR *p);
-static TCHAR* SkipXMLProlog(TCHAR *p);
-static TCHAR* SkipPCData(TCHAR *p);
-static int IsPCData(TCHAR *p);
-static void ConvertBuiltInEntities(TCHAR* p);
-static void SetToken(int type, TCHAR* start, TCHAR* end);
-static void GetNextToken(void);
-static XMLNode* CreateXMLNode(int type, TCHAR* name);
-static XMLAttribute* CreateXMLAttribute(TCHAR *name, TCHAR* value);
-static XMLNode* ParseXMLElement(void);
-static XMLAttribute* ParseXMLAttribute(void);
-static void FreeXMLAttribute(XMLAttribute* attr);
-static void PrintXMLAttributes(XMLAttribute* attr);
-static void indent(int indt);
-
-static jmp_buf jmpbuf;
-static XMLNode* root_node = NULL;
-
-/** definition of error codes for setjmp/longjmp,
- *  that can be handled in ParseXMLDocument()
- */
-#define JMP_NO_ERROR     0
-#define JMP_OUT_OF_RANGE 1
-
-#define NEXT_CHAR(p) { \
-    if (*p != 0) { \
-        p++; \
-    } else { \
-        longjmp(jmpbuf, JMP_OUT_OF_RANGE); \
-    } \
-}
-#define NEXT_CHAR_OR_BREAK(p) { \
-    if (*p != 0) { \
-        p++; \
-    } else { \
-        break; \
-    } \
-}
-#define NEXT_CHAR_OR_RETURN(p) { \
-    if (*p != 0) { \
-        p++; \
-    } else { \
-        return; \
-    } \
-}
-#define SKIP_CHARS(p,n) { \
-    int i; \
-    for (i = 0; i < (n); i++) { \
-        if (*p != 0) { \
-            p++; \
-        } else { \
-           longjmp(jmpbuf, JMP_OUT_OF_RANGE); \
-        } \
-    } \
-}
-#define SKIP_CHARS_OR_BREAK(p,n) { \
-    int i; \
-    for (i = 0; i < (n); i++) { \
-        if (*p != 0) { \
-            p++; \
-        } else { \
-            break; \
-        } \
-    } \
-    if (i < (n)) { \
-        break; \
-    } \
-}
-
-/** Iterates through the null-terminated buffer (i.e., C string) and
- *  replaces all UTF-8 encoded character >255 with 255
- *
- *  UTF-8 encoding:
- *
- *   Range A:  0x0000 - 0x007F
- *                               0 | bits 0 - 7
- *   Range B : 0x0080 - 0x07FF  :
- *                               110 | bits 6 - 10
- *                               10  | bits 0 - 5
- *   Range C : 0x0800 - 0xFFFF  :
- *                               1110 | bits 12-15
- *                               10   | bits  6-11
- *                               10   | bits  0-5
- */
-static void RemoveNonAsciiUTF8FromBuffer(char *buf) {
-    char* p;
-    char* q;
-    char c;
-    p = q = buf;
-    // We are not using NEXT_CHAR() to check if *q is NULL, as q is output
-    // location and offset for q is smaller than for p.
-    while (*p != '\0') {
-        c = *p;
-        if ((c & 0x80) == 0) {
-            /* Range A */
-            *q++ = *p;
-            NEXT_CHAR(p);
-        } else if ((c & 0xE0) == 0xC0) {
-            /* Range B */
-            *q++ = (char) 0xFF;
-            NEXT_CHAR(p);
-            NEXT_CHAR_OR_BREAK(p);
-        } else {
-            /* Range C */
-            *q++ = (char) 0xFF;
-            NEXT_CHAR(p);
-            SKIP_CHARS_OR_BREAK(p, 2);
-        }
-    }
-    /* Null terminate string */
-    *q = '\0';
-}
-
-static TCHAR* SkipWhiteSpace(TCHAR *p) {
-    if (p != NULL) {
-        while (iswspace(*p))
-            NEXT_CHAR_OR_BREAK(p);
-    }
-    return p;
-}
-
-static TCHAR* SkipXMLName(TCHAR *p) {
-    TCHAR c = *p;
-    /* Check if start of token */
-    if (('a' <= c && c <= 'z') ||
-            ('A' <= c && c <= 'Z') ||
-            c == '_' || c == ':') {
-
-        while (('a' <= c && c <= 'z') ||
-                ('A' <= c && c <= 'Z') ||
-                ('0' <= c && c <= '9') ||
-                c == '_' || c == ':' || c == '.' || c == '-') {
-            NEXT_CHAR(p);
-            c = *p;
-            if (c == '\0') break;
-        }
-    }
-    return p;
-}
-
-static TCHAR* SkipXMLComment(TCHAR *p) {
-    if (p != NULL) {
-        if (JPACKAGE_STRNCMP(p, _T("<!--"), 4) == 0) {
-            SKIP_CHARS(p, 4);
-            do {
-                if (JPACKAGE_STRNCMP(p, _T("-->"), 3) == 0) {
-                    SKIP_CHARS(p, 3);
-                    return p;
-                }
-                NEXT_CHAR(p);
-            } while (*p != '\0');
-        }
-    }
-    return p;
-}
-
-static TCHAR* SkipXMLDocType(TCHAR *p) {
-    if (p != NULL) {
-        if (JPACKAGE_STRNCMP(p, _T("<!"), 2) == 0) {
-            SKIP_CHARS(p, 2);
-            while (*p != '\0') {
-                if (*p == '>') {
-                    NEXT_CHAR(p);
-                    return p;
-                }
-                NEXT_CHAR(p);
-            }
-        }
-    }
-    return p;
-}
-
-static TCHAR* SkipXMLProlog(TCHAR *p) {
-    if (p != NULL) {
-        if (JPACKAGE_STRNCMP(p, _T("<?"), 2) == 0) {
-            SKIP_CHARS(p, 2);
-            do {
-                if (JPACKAGE_STRNCMP(p, _T("?>"), 2) == 0) {
-                    SKIP_CHARS(p, 2);
-                    return p;
-                }
-                NEXT_CHAR(p);
-            } while (*p != '\0');
-        }
-    }
-    return p;
-}
-
-/* Search for the built-in XML entities:
- * &amp; (&), &lt; (<), &gt; (>), &apos; ('), and &quote(")
- * and convert them to a real TCHARacter
- */
-static void ConvertBuiltInEntities(TCHAR* p) {
-    TCHAR* q;
-    q = p;
-    // We are not using NEXT_CHAR() to check if *q is NULL,
-    // as q is output location and offset for q is smaller than for p.
-    while (*p) {
-        if (IsPCData(p)) {
-            /* dont convert &xxx values within PData */
-            TCHAR *end;
-            end = SkipPCData(p);
-            while (p < end) {
-                *q++ = *p;
-                NEXT_CHAR(p);
-            }
-        } else {
-            if (JPACKAGE_STRNCMP(p, _T("&amp;"), 5) == 0) {
-                *q++ = '&';
-                SKIP_CHARS(p, 5);
-            } else if (JPACKAGE_STRNCMP(p, _T("&lt;"), 4) == 0) {
-                *q = '<';
-                SKIP_CHARS(p, 4);
-            } else if (JPACKAGE_STRNCMP(p, _T("&gt;"), 4) == 0) {
-                *q = '>';
-                SKIP_CHARS(p, 4);
-            } else if (JPACKAGE_STRNCMP(p, _T("&apos;"), 6) == 0) {
-                *q = '\'';
-                SKIP_CHARS(p, 6);
-            } else if (JPACKAGE_STRNCMP(p, _T("&quote;"), 7) == 0) {
-                *q = '\"';
-                SKIP_CHARS(p, 7);
-            } else {
-                *q++ = *p;
-                NEXT_CHAR(p);
-            }
-        }
-    }
-    *q = '\0';
-}
-
-/* ------------------------------------------------------------- */
-/* XML tokenizer */
-
-#define TOKEN_UNKNOWN             0
-#define TOKEN_BEGIN_TAG           1  /* <tag */
-#define TOKEN_END_TAG             2  /* </tag */
-#define TOKEN_CLOSE_BRACKET       3  /* >  */
-#define TOKEN_EMPTY_CLOSE_BRACKET 4  /* /> */
-#define TOKEN_PCDATA              5  /* pcdata */
-#define TOKEN_CDATA               6  /* cdata */
-#define TOKEN_EOF                 7
-
-static TCHAR* CurPos = NULL;
-static TCHAR* CurTokenName = NULL;
-static int CurTokenType;
-static int MaxTokenSize = -1;
-
-/* Copy token from buffer to Token variable */
-static void SetToken(int type, TCHAR* start, TCHAR* end) {
-    int len = end - start;
-    if (len > MaxTokenSize) {
-        if (CurTokenName != NULL) free(CurTokenName);
-        CurTokenName = (TCHAR *) malloc((len + 1) * sizeof (TCHAR));
-        if (CurTokenName == NULL) {
-            return;
-        }
-        MaxTokenSize = len;
-    }
-
-    CurTokenType = type;
-    JPACKAGE_STRNCPY(CurTokenName, len + 1, start, len);
-    CurTokenName[len] = '\0';
-}
-
-/* Skip XML comments, doctypes, and prolog tags */
-static TCHAR* SkipFilling(void) {
-    TCHAR *q = CurPos;
-
-    /* Skip white space and comment sections */
-    do {
-        q = CurPos;
-        CurPos = SkipWhiteSpace(CurPos);
-        CurPos = SkipXMLComment(CurPos); /* Must be called befor DocTypes */
-        CurPos = SkipXMLDocType(CurPos); /* <! ... > directives */
-        CurPos = SkipXMLProlog(CurPos); /* <? ... ?> directives */
-    } while (CurPos != q);
-
-    return CurPos;
-}
-
-/* Parses next token and initializes the global token variables above
-   The tokennizer automatically skips comments (<!-- comment -->) and
-   <! ... > directives.
- */
-static void GetNextToken(void) {
-    TCHAR *p, *q;
-
-    /* Skip white space and comment sections */
-    p = SkipFilling();
-
-    if (p == NULL || *p == '\0') {
-        CurTokenType = TOKEN_EOF;
-        return;
-    } else if (p[0] == '<' && p[1] == '/') {
-        /* TOKEN_END_TAG */
-        q = SkipXMLName(p + 2);
-        SetToken(TOKEN_END_TAG, p + 2, q);
-        p = q;
-    } else if (*p == '<') {
-        /* TOKEN_BEGIN_TAG */
-        q = SkipXMLName(p + 1);
-        SetToken(TOKEN_BEGIN_TAG, p + 1, q);
-        p = q;
-    } else if (p[0] == '>') {
-        CurTokenType = TOKEN_CLOSE_BRACKET;
-        NEXT_CHAR(p);
-    } else if (p[0] == '/' && p[1] == '>') {
-        CurTokenType = TOKEN_EMPTY_CLOSE_BRACKET;
-        SKIP_CHARS(p, 2);
-    } else {
-        /* Search for end of data */
-        q = p + 1;
-        while (*q && *q != '<') {
-            if (IsPCData(q)) {
-                q = SkipPCData(q);
-            } else {
-                NEXT_CHAR(q);
-            }
-        }
-        SetToken(TOKEN_PCDATA, p, q);
-        /* Convert all entities inside token */
-        ConvertBuiltInEntities(CurTokenName);
-        p = q;
-    }
-    /* Advance pointer to beginning of next token */
-    CurPos = p;
-}
-
-static XMLNode* CreateXMLNode(int type, TCHAR* name) {
-    XMLNode* node;
-    node = (XMLNode*) malloc(sizeof (XMLNode));
-    if (node == NULL) {
-        return NULL;
-    }
-    node->_type = type;
-    node->_name = name;
-    node->_next = NULL;
-    node->_sub = NULL;
-    node->_attributes = NULL;
-    return node;
-}
-
-static XMLAttribute* CreateXMLAttribute(TCHAR *name, TCHAR* value) {
-    XMLAttribute* attr;
-    attr = (XMLAttribute*) malloc(sizeof (XMLAttribute));
-    if (attr == NULL) {
-        return NULL;
-    }
-    attr->_name = name;
-    attr->_value = value;
-    attr->_next = NULL;
-    return attr;
-}
-
-XMLNode* ParseXMLDocument(TCHAR* buf) {
-    XMLNode* root;
-    int err_code = setjmp(jmpbuf);
-    switch (err_code) {
-        case JMP_NO_ERROR:
-#ifndef _UNICODE
-            /* Remove UTF-8 encoding from buffer */
-            RemoveNonAsciiUTF8FromBuffer(buf);
-#endif
-
-            /* Get first Token */
-            CurPos = buf;
-            GetNextToken();
-
-            /* Parse document*/
-            root = ParseXMLElement();
-            break;
-        case JMP_OUT_OF_RANGE:
-            /* cleanup: */
-            if (root_node != NULL) {
-                FreeXMLDocument(root_node);
-                root_node = NULL;
-            }
-            if (CurTokenName != NULL) free(CurTokenName);
-            fprintf(stderr, "Error during parsing jnlp file...\n");
-            exit(-1);
-            break;
-        default:
-            root = NULL;
-            break;
-    }
-
-    return root;
-}
-
-static XMLNode* ParseXMLElement(void) {
-    XMLNode* node = NULL;
-    XMLNode* subnode = NULL;
-    XMLNode* nextnode = NULL;
-    XMLAttribute* attr = NULL;
-
-    if (CurTokenType == TOKEN_BEGIN_TAG) {
-
-        /* Create node for new element tag */
-        node = CreateXMLNode(xmlTagType, JPACKAGE_STRDUP(CurTokenName));
-        /* We need to save root node pointer to be able to cleanup
-           if an error happens during parsing */
-        if (!root_node) {
-            root_node = node;
-        }
-        /* Parse attributes. This section eats a all input until
-           EOF, a > or a /> */
-        attr = ParseXMLAttribute();
-        while (attr != NULL) {
-            attr->_next = node->_attributes;
-            node->_attributes = attr;
-            attr = ParseXMLAttribute();
-        }
-
-        /* This will eihter be a TOKEN_EOF, TOKEN_CLOSE_BRACKET, or a
-         * TOKEN_EMPTY_CLOSE_BRACKET */
-        GetNextToken();
-
-        if (CurTokenType == TOKEN_EMPTY_CLOSE_BRACKET) {
-            GetNextToken();
-            /* We are done with the sublevel - fall through to continue */
-            /* parsing tags at the same level */
-        } else if (CurTokenType == TOKEN_CLOSE_BRACKET) {
-            GetNextToken();
-
-            /* Parse until end tag if found */
-            node->_sub = ParseXMLElement();
-
-            if (CurTokenType == TOKEN_END_TAG) {
-                /* Find closing bracket '>' for end tag */
-                do {
-                    GetNextToken();
-                } while (CurTokenType != TOKEN_EOF &&
-                        CurTokenType != TOKEN_CLOSE_BRACKET);
-                GetNextToken();
-            }
-        }
-
-        /* Continue parsing rest on same level */
-        if (CurTokenType != TOKEN_EOF) {
-            /* Parse rest of stream at same level */
-            node->_next = ParseXMLElement();
-        }
-        return node;
-
-    } else if (CurTokenType == TOKEN_PCDATA) {
-        /* Create node for pcdata */
-        node = CreateXMLNode(xmlPCDataType, JPACKAGE_STRDUP(CurTokenName));
-        /* We need to save root node pointer to be able to cleanup
-           if an error happens during parsing */
-        if (!root_node) {
-            root_node = node;
-        }
-        GetNextToken();
-        return node;
-    }
-
-    /* Something went wrong. */
-    return NULL;
-}
-
-/* Parses an XML attribute. */
-static XMLAttribute* ParseXMLAttribute(void) {
-    TCHAR* q = NULL;
-    TCHAR* name = NULL;
-    TCHAR* PrevPos = NULL;
-
-    do {
-        /* We need to check this condition to avoid endless loop
-           in case if an error happend during parsing. */
-        if (PrevPos == CurPos) {
-            if (name != NULL) {
-                free(name);
-                name = NULL;
-            }
-
-            return NULL;
-        }
-
-        PrevPos = CurPos;
-
-        /* Skip whitespace etc. */
-        SkipFilling();
-
-        /* Check if we are done witht this attribute section */
-        if (CurPos[0] == '\0' ||
-                CurPos[0] == '>' ||
-                (CurPos[0] == '/' && CurPos[1] == '>')) {
-
-            if (name != NULL) {
-                free(name);
-                name = NULL;
-            }
-
-            return NULL;
-        }
-
-        /* Find end of name */
-        q = CurPos;
-        while (*q && !iswspace(*q) && *q != '=') NEXT_CHAR(q);
-
-        SetToken(TOKEN_UNKNOWN, CurPos, q);
-        if (name) {
-            free(name);
-            name = NULL;
-        }
-        name = JPACKAGE_STRDUP(CurTokenName);
-
-        /* Skip any whitespace */
-        CurPos = q;
-        CurPos = SkipFilling();
-
-        /* Next TCHARacter must be '=' for a valid attribute.
-           If it is not, this is really an error.
-           We ignore this, and just try to parse an attribute
-           out of the rest of the string.
-         */
-    } while (*CurPos != '=');
-
-    NEXT_CHAR(CurPos);
-    CurPos = SkipWhiteSpace(CurPos);
-    /* Parse CDATA part of attribute */
-    if ((*CurPos == '\"') || (*CurPos == '\'')) {
-        TCHAR quoteChar = *CurPos;
-        q = ++CurPos;
-        while (*q != '\0' && *q != quoteChar) NEXT_CHAR(q);
-        SetToken(TOKEN_CDATA, CurPos, q);
-        CurPos = q + 1;
-    } else {
-        q = CurPos;
-        while (*q != '\0' && !iswspace(*q)) NEXT_CHAR(q);
-        SetToken(TOKEN_CDATA, CurPos, q);
-        CurPos = q;
-    }
-
-    //Note: no need to free name and CurTokenName duplicate; they're assigned
-    // to an XMLAttribute structure in CreateXMLAttribute
-
-    return CreateXMLAttribute(name, JPACKAGE_STRDUP(CurTokenName));
-}
-
-void FreeXMLDocument(XMLNode* root) {
-    if (root == NULL) return;
-    FreeXMLDocument(root->_sub);
-    FreeXMLDocument(root->_next);
-    FreeXMLAttribute(root->_attributes);
-    free(root->_name);
-    free(root);
-}
-
-static void FreeXMLAttribute(XMLAttribute* attr) {
-    if (attr == NULL) return;
-    free(attr->_name);
-    free(attr->_value);
-    FreeXMLAttribute(attr->_next);
-    free(attr);
-}
-
-/* Find element at current level with a given name */
-XMLNode* FindXMLChild(XMLNode* root, const TCHAR* name) {
-    if (root == NULL) return NULL;
-
-    if (root->_type == xmlTagType && JPACKAGE_STRCMP(root->_name, name) == 0) {
-        return root;
-    }
-
-    return FindXMLChild(root->_next, name);
-}
-
-/* Search for an attribute with the given name and returns the contents.
- * Returns NULL if attribute is not found
- */
-TCHAR* FindXMLAttribute(XMLAttribute* attr, const TCHAR* name) {
-    if (attr == NULL) return NULL;
-    if (JPACKAGE_STRCMP(attr->_name, name) == 0) return attr->_value;
-    return FindXMLAttribute(attr->_next, name);
-}
-
-void PrintXMLDocument(XMLNode* node, int indt) {
-    if (node == NULL) return;
-
-    if (node->_type == xmlTagType) {
-        JPACKAGE_PRINTF(_T("\n"));
-        indent(indt);
-        JPACKAGE_PRINTF(_T("<%s"), node->_name);
-        PrintXMLAttributes(node->_attributes);
-        if (node->_sub == NULL) {
-            JPACKAGE_PRINTF(_T("/>\n"));
-        } else {
-            JPACKAGE_PRINTF(_T(">"));
-            PrintXMLDocument(node->_sub, indt + 1);
-            indent(indt);
-            JPACKAGE_PRINTF(_T("</%s>"), node->_name);
-        }
-    } else {
-        JPACKAGE_PRINTF(_T("%s"), node->_name);
-    }
-    PrintXMLDocument(node->_next, indt);
-}
-
-static void PrintXMLAttributes(XMLAttribute* attr) {
-    if (attr == NULL) return;
-
-    JPACKAGE_PRINTF(_T(" %s=\"%s\""), attr->_name, attr->_value);
-    PrintXMLAttributes(attr->_next);
-}
-
-static void indent(int indt) {
-    int i;
-    for (i = 0; i < indt; i++) {
-        JPACKAGE_PRINTF(_T("  "));
-    }
-}
-
-const TCHAR *CDStart = _T("<![CDATA[");
-const TCHAR *CDEnd = _T("]]>");
-
-static TCHAR* SkipPCData(TCHAR *p) {
-    TCHAR *end = JPACKAGE_STRSTR(p, CDEnd);
-    if (end != NULL) {
-        return end + sizeof (CDEnd);
-    }
-    return (++p);
-}
-
-static int IsPCData(TCHAR *p) {
-    const int size = sizeof (CDStart);
-    return (JPACKAGE_STRNCMP(CDStart, p, size) == 0);
-}
--- a/src/jdk.jpackage/linux/native/libapplauncher/LinuxPlatform.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef LINUXPLATFORM_H
-#define LINUXPLATFORM_H
-
-#include "Platform.h"
-#include "PosixPlatform.h"
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <pthread.h>
-#include <list>
-
-class LinuxPlatform : virtual public Platform, PosixPlatform {
-private:
-    pthread_t FMainThread;
-
-protected:
-    virtual TString getTmpDirString();
-
-public:
-    LinuxPlatform(void);
-    virtual ~LinuxPlatform(void);
-
-    TString GetPackageAppDirectory();
-    TString GetPackageLauncherDirectory();
-    TString GetPackageRuntimeBinDirectory();
-
-    virtual void ShowMessage(TString title, TString description);
-    virtual void ShowMessage(TString description);
-
-    virtual TCHAR* ConvertStringToFileSystemString(
-            TCHAR* Source, bool &release);
-    virtual TCHAR* ConvertFileSystemStringToString(
-            TCHAR* Source, bool &release);
-
-    virtual TString GetPackageRootDirectory();
-    virtual TString GetAppDataDirectory();
-    virtual TString GetAppName();
-
-    virtual TString GetModuleFileName();
-
-    virtual TString GetBundledJavaLibraryFileName(TString RuntimePath);
-
-    virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
-
-    virtual bool IsMainThread();
-    virtual TPlatformNumber GetMemorySize();
-};
-
-#endif //LINUXPLATFORM_H
--- a/src/jdk.jpackage/linux/native/libapplauncher/PlatformDefs.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef PLATFORM_DEFS_H
-#define PLATFORM_DEFS_H
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <dlfcn.h>
-#include <libgen.h>
-#include <string>
-
-using namespace std;
-
-#ifndef LINUX
-#define LINUX
-#endif
-
-#define _T(x) x
-
-typedef char TCHAR;
-typedef std::string TString;
-#define StringLength strlen
-
-typedef unsigned long DWORD;
-
-#define TRAILING_PATHSEPARATOR '/'
-#define BAD_TRAILING_PATHSEPARATOR '\\'
-#define PATH_SEPARATOR ':'
-#define BAD_PATH_SEPARATOR ';'
-#define MAX_PATH 1000
-
-typedef long TPlatformNumber;
-typedef pid_t TProcessID;
-
-#define HMODULE void*
-
-typedef void* Module;
-typedef void* Procedure;
-
-#define StringToFileSystemString PlatformString
-#define FileSystemStringToString PlatformString
-
-#endif // PLATFORM_DEFS_H
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/EnumeratedBundlerParam.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.*;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-
-/**
- * EnumeratedBundlerParams<T>
- *
- * Contains key-value pairs (elements) where keys are "displayable"
- * keys which the IDE can display/choose and values are "identifier" values
- * which can be stored in parameters' map.
- *
- * For instance the Mac has a predefined set of categories which can be applied
- * to LSApplicationCategoryType which is required for the mac app store.
- *
- * The following example illustrates a simple usage of
- *     the MAC_CATEGORY parameter:
- *
- * <pre>{@code
- *     Set<String> keys = MAC_CATEGORY.getDisplayableKeys();
- *
- *     String key = getLastValue(keys); // get last value for example
- *
- *     String value = MAC_CATEGORY.getValueForDisplayableKey(key);
- *     params.put(MAC_CATEGORY.getID(), value);
- * }</pre>
- *
- */
-class EnumeratedBundlerParam<T> extends BundlerParamInfo<T> {
-    // Not sure if this is the correct order, my idea is that from IDE
-    // perspective the string to display to the user is the key and then the
-    // value is some type of object (although probably a String in most cases)
-    private final Map<String, T> elements;
-    private final boolean strict;
-
-    EnumeratedBundlerParam(String id, Class<T> valueType,
-            Function<Map<String, ? super Object>, T> defaultValueFunction,
-            BiFunction<String, Map<String, ? super Object>, T> stringConverter,
-            Map<String, T> elements, boolean strict) {
-        this.id = id;
-        this.valueType = valueType;
-        this.defaultValueFunction = defaultValueFunction;
-        this.stringConverter = stringConverter;
-        this.elements = elements;
-        this.strict = strict;
-    }
-
-    boolean isInPossibleValues(T value) {
-        return elements.values().contains(value);
-    }
-
-    // Having the displayable values as the keys seems a bit wacky
-    Set<String> getDisplayableKeys() {
-        return Collections.unmodifiableSet(elements.keySet());
-    }
-
-    // mapping from a "displayable" key to an "identifier" value.
-    T getValueForDisplayableKey(String displayableKey) {
-        return elements.get(displayableKey);
-    }
-
-    boolean isStrict() {
-        return strict;
-    }
-
-    boolean isLoose() {
-        return !isStrict();
-    }
-
-}
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.File;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.ResourceBundle;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-import static jdk.jpackage.internal.MacBaseInstallerBundler.*;
-
-public class MacAppBundler extends AbstractImageBundler {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MacResources");
-
-    private static final String TEMPLATE_BUNDLE_ICON = "java.icns";
-
-    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.MAC_BUNDLE_NAME.getId(),
-                    String.class,
-                    params -> null,
-                    (s, p) -> s);
-
-    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION =
-            new StandardBundlerParam<>(
-                    "mac.CFBundleVersion",
-                    String.class,
-                    p -> {
-                        String s = VERSION.fetchFrom(p);
-                        if (validCFBundleVersion(s)) {
-                            return s;
-                        } else {
-                            return "100";
-                        }
-                    },
-                    (s, p) -> s);
-
-    public static final BundlerParamInfo<String> DEFAULT_ICNS_ICON =
-            new StandardBundlerParam<>(
-            ".mac.default.icns",
-            String.class,
-            params -> TEMPLATE_BUNDLE_ICON,
-            (s, p) -> s);
-
-    public static final BundlerParamInfo<String> DEVELOPER_ID_APP_SIGNING_KEY =
-            new StandardBundlerParam<>(
-            "mac.signing-key-developer-id-app",
-            String.class,
-            params -> {
-                    String result = MacBaseInstallerBundler.findKey(
-                            "Developer ID Application: "
-                            + SIGNING_KEY_USER.fetchFrom(params),
-                            SIGNING_KEYCHAIN.fetchFrom(params),
-                            VERBOSE.fetchFrom(params));
-                    if (result != null) {
-                        MacCertificate certificate = new MacCertificate(result);
-
-                        if (!certificate.isValid()) {
-                            Log.error(MessageFormat.format(I18N.getString(
-                                    "error.certificate.expired"), result));
-                        }
-                    }
-
-                    return result;
-                },
-            (s, p) -> s);
-
-    public static final BundlerParamInfo<String> BUNDLE_ID_SIGNING_PREFIX =
-            new StandardBundlerParam<>(
-            Arguments.CLIOptions.MAC_BUNDLE_SIGNING_PREFIX.getId(),
-            String.class,
-            params -> IDENTIFIER.fetchFrom(params) + ".",
-            (s, p) -> s);
-
-    public static final BundlerParamInfo<File> ICON_ICNS =
-            new StandardBundlerParam<>(
-            "icon.icns",
-            File.class,
-            params -> {
-                File f = ICON.fetchFrom(params);
-                if (f != null && !f.getName().toLowerCase().endsWith(".icns")) {
-                    Log.error(MessageFormat.format(
-                            I18N.getString("message.icon-not-icns"), f));
-                    return null;
-                }
-                return f;
-            },
-            (s, p) -> new File(s));
-
-    public static boolean validCFBundleVersion(String v) {
-        // CFBundleVersion (String - iOS, OS X) specifies the build version
-        // number of the bundle, which identifies an iteration (released or
-        // unreleased) of the bundle. The build version number should be a
-        // string comprised of three non-negative, period-separated integers
-        // with the first integer being greater than zero. The string should
-        // only contain numeric (0-9) and period (.) characters. Leading zeros
-        // are truncated from each integer and will be ignored (that is,
-        // 1.02.3 is equivalent to 1.2.3). This key is not localizable.
-
-        if (v == null) {
-            return false;
-        }
-
-        String p[] = v.split("\\.");
-        if (p.length > 3 || p.length < 1) {
-            Log.verbose(I18N.getString(
-                    "message.version-string-too-many-components"));
-            return false;
-        }
-
-        try {
-            BigInteger n = new BigInteger(p[0]);
-            if (BigInteger.ONE.compareTo(n) > 0) {
-                Log.verbose(I18N.getString(
-                        "message.version-string-first-number-not-zero"));
-                return false;
-            }
-            if (p.length > 1) {
-                n = new BigInteger(p[1]);
-                if (BigInteger.ZERO.compareTo(n) > 0) {
-                    Log.verbose(I18N.getString(
-                            "message.version-string-no-negative-numbers"));
-                    return false;
-                }
-            }
-            if (p.length > 2) {
-                n = new BigInteger(p[2]);
-                if (BigInteger.ZERO.compareTo(n) > 0) {
-                    Log.verbose(I18N.getString(
-                            "message.version-string-no-negative-numbers"));
-                    return false;
-                }
-            }
-        } catch (NumberFormatException ne) {
-            Log.verbose(I18N.getString("message.version-string-numbers-only"));
-            Log.verbose(ne);
-            return false;
-        }
-
-        return true;
-    }
-
-    @Override
-    public boolean validate(Map<String, ? super Object> params)
-            throws ConfigException {
-        try {
-            return doValidate(params);
-        } catch (RuntimeException re) {
-            if (re.getCause() instanceof ConfigException) {
-                throw (ConfigException) re.getCause();
-            } else {
-                throw new ConfigException(re);
-            }
-        }
-    }
-
-    private boolean doValidate(Map<String, ? super Object> params)
-            throws ConfigException {
-
-        imageBundleValidation(params);
-
-        if (StandardBundlerParam.getPredefinedAppImage(params) != null) {
-            return true;
-        }
-
-        // validate short version
-        if (!validCFBundleVersion(MAC_CF_BUNDLE_VERSION.fetchFrom(params))) {
-            throw new ConfigException(
-                    I18N.getString("error.invalid-cfbundle-version"),
-                    I18N.getString("error.invalid-cfbundle-version.advice"));
-        }
-
-        // reject explicitly set sign to true and no valid signature key
-        if (Optional.ofNullable(MacAppImageBuilder.
-                    SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) {
-            String signingIdentity =
-                    DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
-            if (signingIdentity == null) {
-                throw new ConfigException(
-                        I18N.getString("error.explicit-sign-no-cert"),
-                        I18N.getString("error.explicit-sign-no-cert.advice"));
-            }
-
-            // Signing will not work without Xcode with command line developer tools
-            try {
-                ProcessBuilder pb = new ProcessBuilder("xcrun", "--help");
-                Process p = pb.start();
-                int code = p.waitFor();
-                if (code != 0) {
-                    throw new ConfigException(
-                        I18N.getString("error.no.xcode.signing"),
-                        I18N.getString("error.no.xcode.signing.advice"));
-                }
-            } catch (IOException | InterruptedException ex) {
-                throw new ConfigException(ex);
-            }
-        }
-
-        return true;
-    }
-
-    File doBundle(Map<String, ? super Object> params, File outputDirectory,
-            boolean dependentTask) throws PackagerException {
-        if (StandardBundlerParam.isRuntimeInstaller(params)) {
-            return PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
-        } else {
-            return doAppBundle(params, outputDirectory, dependentTask);
-        }
-    }
-
-    File doAppBundle(Map<String, ? super Object> params, File outputDirectory,
-            boolean dependentTask) throws PackagerException {
-        try {
-            File rootDirectory = createRoot(params, outputDirectory,
-                    dependentTask, APP_NAME.fetchFrom(params) + ".app");
-            AbstractAppImageBuilder appBuilder =
-                    new MacAppImageBuilder(params, outputDirectory.toPath());
-            if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(params) == null ) {
-                JLinkBundlerHelper.execute(params, appBuilder);
-            } else {
-                StandardBundlerParam.copyPredefinedRuntimeImage(
-                        params, appBuilder);
-            }
-            return rootDirectory;
-        } catch (PackagerException pe) {
-            throw pe;
-        } catch (Exception ex) {
-            Log.verbose(ex);
-            throw new PackagerException(ex);
-        }
-    }
-
-    /////////////////////////////////////////////////////////////////////////
-    // Implement Bundler
-    /////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public String getName() {
-        return I18N.getString("app.bundler.name");
-    }
-
-    @Override
-    public String getID() {
-        return "mac.app";
-    }
-
-    @Override
-    public String getBundleType() {
-        return "IMAGE";
-    }
-
-    @Override
-    public File execute(Map<String, ? super Object> params,
-            File outputParentDir) throws PackagerException {
-        return doBundle(params, outputParentDir, false);
-    }
-
-    @Override
-    public boolean supported(boolean runtimeInstaller) {
-        return true;
-    }
-
-    @Override
-    public boolean isDefault() {
-        return false;
-    }
-
-}
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,945 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Writer;
-import java.math.BigInteger;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.nio.file.attribute.PosixFilePermission;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.ResourceBundle;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathFactory;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-import static jdk.jpackage.internal.MacBaseInstallerBundler.*;
-import static jdk.jpackage.internal.MacAppBundler.*;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-
-public class MacAppImageBuilder extends AbstractAppImageBuilder {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MacResources");
-
-    private static final String LIBRARY_NAME = "libapplauncher.dylib";
-    private static final String TEMPLATE_BUNDLE_ICON = "java.icns";
-    private static final String OS_TYPE_CODE = "APPL";
-    private static final String TEMPLATE_INFO_PLIST_LITE =
-            "Info-lite.plist.template";
-    private static final String TEMPLATE_RUNTIME_INFO_PLIST =
-            "Runtime-Info.plist.template";
-
-    private final Path root;
-    private final Path contentsDir;
-    private final Path appDir;
-    private final Path javaModsDir;
-    private final Path resourcesDir;
-    private final Path macOSDir;
-    private final Path runtimeDir;
-    private final Path runtimeRoot;
-    private final Path mdir;
-
-    private static List<String> keyChains;
-
-    public static final BundlerParamInfo<Boolean>
-            MAC_CONFIGURE_LAUNCHER_IN_PLIST = new StandardBundlerParam<>(
-                    "mac.configure-launcher-in-plist",
-                    Boolean.class,
-                    params -> Boolean.FALSE,
-                    (s, p) -> Boolean.valueOf(s));
-
-    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.MAC_BUNDLE_NAME.getId(),
-                    String.class,
-                    params -> null,
-                    (s, p) -> s);
-
-    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_IDENTIFIER =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(),
-                    String.class,
-                    params -> {
-                        // Get identifier from app image if user provided
-                        // app image and did not provide the identifier via CLI.
-                        String identifier = extractBundleIdentifier(params);
-                        if (identifier != null) {
-                            return identifier;
-                        }
-
-                        return IDENTIFIER.fetchFrom(params);
-                    },
-                    (s, p) -> s);
-
-    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION =
-            new StandardBundlerParam<>(
-                    "mac.CFBundleVersion",
-                    String.class,
-                    p -> {
-                        String s = VERSION.fetchFrom(p);
-                        if (validCFBundleVersion(s)) {
-                            return s;
-                        } else {
-                            return "100";
-                        }
-                    },
-                    (s, p) -> s);
-
-    public static final BundlerParamInfo<File> ICON_ICNS =
-            new StandardBundlerParam<>(
-            "icon.icns",
-            File.class,
-            params -> {
-                File f = ICON.fetchFrom(params);
-                if (f != null && !f.getName().toLowerCase().endsWith(".icns")) {
-                    Log.error(MessageFormat.format(
-                            I18N.getString("message.icon-not-icns"), f));
-                    return null;
-                }
-                return f;
-            },
-            (s, p) -> new File(s));
-
-    public static final StandardBundlerParam<Boolean> SIGN_BUNDLE  =
-            new StandardBundlerParam<>(
-            Arguments.CLIOptions.MAC_SIGN.getId(),
-            Boolean.class,
-            params -> false,
-            // valueOf(null) is false, we actually do want null in some cases
-            (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
-                    null : Boolean.valueOf(s)
-        );
-
-    public MacAppImageBuilder(Map<String, Object> params, Path imageOutDir)
-            throws IOException {
-        super(params, imageOutDir.resolve(APP_NAME.fetchFrom(params)
-                + ".app/Contents/runtime/Contents/Home"));
-
-        Objects.requireNonNull(imageOutDir);
-
-        this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params) + ".app");
-        this.contentsDir = root.resolve("Contents");
-        this.appDir = contentsDir.resolve("app");
-        this.javaModsDir = appDir.resolve("mods");
-        this.resourcesDir = contentsDir.resolve("Resources");
-        this.macOSDir = contentsDir.resolve("MacOS");
-        this.runtimeDir = contentsDir.resolve("runtime");
-        this.runtimeRoot = runtimeDir.resolve("Contents/Home");
-        this.mdir = runtimeRoot.resolve("lib");
-        Files.createDirectories(appDir);
-        Files.createDirectories(resourcesDir);
-        Files.createDirectories(macOSDir);
-        Files.createDirectories(runtimeDir);
-    }
-
-    private void writeEntry(InputStream in, Path dstFile) throws IOException {
-        Files.createDirectories(dstFile.getParent());
-        Files.copy(in, dstFile);
-    }
-
-    public static boolean validCFBundleVersion(String v) {
-        // CFBundleVersion (String - iOS, OS X) specifies the build version
-        // number of the bundle, which identifies an iteration (released or
-        // unreleased) of the bundle. The build version number should be a
-        // string comprised of three non-negative, period-separated integers
-        // with the first integer being greater than zero. The string should
-        // only contain numeric (0-9) and period (.) characters. Leading zeros
-        // are truncated from each integer and will be ignored (that is,
-        // 1.02.3 is equivalent to 1.2.3). This key is not localizable.
-
-        if (v == null) {
-            return false;
-        }
-
-        String p[] = v.split("\\.");
-        if (p.length > 3 || p.length < 1) {
-            Log.verbose(I18N.getString(
-                    "message.version-string-too-many-components"));
-            return false;
-        }
-
-        try {
-            BigInteger n = new BigInteger(p[0]);
-            if (BigInteger.ONE.compareTo(n) > 0) {
-                Log.verbose(I18N.getString(
-                        "message.version-string-first-number-not-zero"));
-                return false;
-            }
-            if (p.length > 1) {
-                n = new BigInteger(p[1]);
-                if (BigInteger.ZERO.compareTo(n) > 0) {
-                    Log.verbose(I18N.getString(
-                            "message.version-string-no-negative-numbers"));
-                    return false;
-                }
-            }
-            if (p.length > 2) {
-                n = new BigInteger(p[2]);
-                if (BigInteger.ZERO.compareTo(n) > 0) {
-                    Log.verbose(I18N.getString(
-                            "message.version-string-no-negative-numbers"));
-                    return false;
-                }
-            }
-        } catch (NumberFormatException ne) {
-            Log.verbose(I18N.getString("message.version-string-numbers-only"));
-            Log.verbose(ne);
-            return false;
-        }
-
-        return true;
-    }
-
-    @Override
-    public Path getAppDir() {
-        return appDir;
-    }
-
-    @Override
-    public Path getAppModsDir() {
-        return javaModsDir;
-    }
-
-    @Override
-    public void prepareApplicationFiles(Map<String, ? super Object> params)
-            throws IOException {
-        Map<String, ? super Object> originalParams = new HashMap<>(params);
-        // Generate PkgInfo
-        File pkgInfoFile = new File(contentsDir.toFile(), "PkgInfo");
-        pkgInfoFile.createNewFile();
-        writePkgInfo(pkgInfoFile);
-
-        Path executable = macOSDir.resolve(getLauncherName(params));
-
-        // create the main app launcher
-        try (InputStream is_launcher =
-                getResourceAsStream("jpackageapplauncher");
-            InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
-            // Copy executable and library to MacOS folder
-            writeEntry(is_launcher, executable);
-            writeEntry(is_lib, macOSDir.resolve(LIBRARY_NAME));
-        }
-        executable.toFile().setExecutable(true, false);
-        // generate main app launcher config file
-        File cfg = new File(root.toFile(), getLauncherCfgName(params));
-        writeCfgFile(params, cfg);
-
-        // create additional app launcher(s) and config file(s)
-        List<Map<String, ? super Object>> entryPoints =
-                StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
-        for (Map<String, ? super Object> entryPoint : entryPoints) {
-            Map<String, ? super Object> tmp =
-                    AddLauncherArguments.merge(originalParams, entryPoint);
-
-            // add executable for add launcher
-            Path addExecutable = macOSDir.resolve(getLauncherName(tmp));
-            try (InputStream is = getResourceAsStream("jpackageapplauncher");) {
-                writeEntry(is, addExecutable);
-            }
-            addExecutable.toFile().setExecutable(true, false);
-
-            // add config file for add launcher
-            cfg = new File(root.toFile(), getLauncherCfgName(tmp));
-            writeCfgFile(tmp, cfg);
-        }
-
-        // Copy class path entries to Java folder
-        copyClassPathEntries(appDir, params);
-
-        /*********** Take care of "config" files *******/
-
-        createResource(TEMPLATE_BUNDLE_ICON, params)
-                .setCategory("icon")
-                .setExternal(ICON_ICNS.fetchFrom(params))
-                .saveToFile(resourcesDir.resolve(APP_NAME.fetchFrom(params)
-                        + ".icns"));
-
-        // copy file association icons
-        for (Map<String, ?
-                super Object> fa : FILE_ASSOCIATIONS.fetchFrom(params)) {
-            File f = FA_ICON.fetchFrom(fa);
-            if (f != null && f.exists()) {
-                try (InputStream in2 = new FileInputStream(f)) {
-                    Files.copy(in2, resourcesDir.resolve(f.getName()));
-                }
-
-            }
-        }
-
-        copyRuntimeFiles(params);
-        sign(params);
-    }
-
-    @Override
-    public void prepareJreFiles(Map<String, ? super Object> params)
-            throws IOException {
-        copyRuntimeFiles(params);
-        sign(params);
-    }
-
-    @Override
-    File getRuntimeImageDir(File runtimeImageTop) {
-        File home = new File(runtimeImageTop, "Contents/Home");
-        return (home.exists() ? home : runtimeImageTop);
-    }
-
-    private void copyRuntimeFiles(Map<String, ? super Object> params)
-            throws IOException {
-        // Generate Info.plist
-        writeInfoPlist(contentsDir.resolve("Info.plist").toFile(), params);
-
-        // generate java runtime info.plist
-        writeRuntimeInfoPlist(
-                runtimeDir.resolve("Contents/Info.plist").toFile(), params);
-
-        // copy library
-        Path runtimeMacOSDir = Files.createDirectories(
-                runtimeDir.resolve("Contents/MacOS"));
-
-        // JDK 9, 10, and 11 have extra '/jli/' subdir
-        Path jli = runtimeRoot.resolve("lib/libjli.dylib");
-        if (!Files.exists(jli)) {
-            jli = runtimeRoot.resolve("lib/jli/libjli.dylib");
-        }
-
-        Files.copy(jli, runtimeMacOSDir.resolve("libjli.dylib"));
-    }
-
-    private void sign(Map<String, ? super Object> params) throws IOException {
-        if (Optional.ofNullable(
-                SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) {
-            try {
-                addNewKeychain(params);
-            } catch (InterruptedException e) {
-                Log.error(e.getMessage());
-            }
-            String signingIdentity =
-                    DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
-            if (signingIdentity != null) {
-                signAppBundle(params, root, signingIdentity,
-                        BUNDLE_ID_SIGNING_PREFIX.fetchFrom(params), null, null);
-            }
-            restoreKeychainList(params);
-        }
-    }
-
-    private String getLauncherName(Map<String, ? super Object> params) {
-        if (APP_NAME.fetchFrom(params) != null) {
-            return APP_NAME.fetchFrom(params);
-        } else {
-            return MAIN_CLASS.fetchFrom(params);
-        }
-    }
-
-    public static String getLauncherCfgName(
-            Map<String, ? super Object> params) {
-        return "Contents/app/" + APP_NAME.fetchFrom(params) + ".cfg";
-    }
-
-    private void copyClassPathEntries(Path javaDirectory,
-            Map<String, ? super Object> params) throws IOException {
-        List<RelativeFileSet> resourcesList =
-                APP_RESOURCES_LIST.fetchFrom(params);
-        if (resourcesList == null) {
-            throw new RuntimeException(
-                    I18N.getString("message.null-classpath"));
-        }
-
-        for (RelativeFileSet classPath : resourcesList) {
-            File srcdir = classPath.getBaseDirectory();
-            for (String fname : classPath.getIncludedFiles()) {
-                copyEntry(javaDirectory, srcdir, fname);
-            }
-        }
-    }
-
-    private String getBundleName(Map<String, ? super Object> params) {
-        if (MAC_CF_BUNDLE_NAME.fetchFrom(params) != null) {
-            String bn = MAC_CF_BUNDLE_NAME.fetchFrom(params);
-            if (bn.length() > 16) {
-                Log.error(MessageFormat.format(I18N.getString(
-                        "message.bundle-name-too-long-warning"),
-                        MAC_CF_BUNDLE_NAME.getID(), bn));
-            }
-            return MAC_CF_BUNDLE_NAME.fetchFrom(params);
-        } else if (APP_NAME.fetchFrom(params) != null) {
-            return APP_NAME.fetchFrom(params);
-        } else {
-            String nm = MAIN_CLASS.fetchFrom(params);
-            if (nm.length() > 16) {
-                nm = nm.substring(0, 16);
-            }
-            return nm;
-        }
-    }
-
-    private void writeRuntimeInfoPlist(File file,
-            Map<String, ? super Object> params) throws IOException {
-        Map<String, String> data = new HashMap<>();
-        String identifier = StandardBundlerParam.isRuntimeInstaller(params) ?
-                MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) :
-                "com.oracle.java." + MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params);
-        data.put("CF_BUNDLE_IDENTIFIER", identifier);
-        String name = StandardBundlerParam.isRuntimeInstaller(params) ?
-                getBundleName(params): "Java Runtime Image";
-        data.put("CF_BUNDLE_NAME", name);
-        data.put("CF_BUNDLE_VERSION", VERSION.fetchFrom(params));
-        data.put("CF_BUNDLE_SHORT_VERSION_STRING", VERSION.fetchFrom(params));
-
-        createResource(TEMPLATE_RUNTIME_INFO_PLIST, params)
-                .setPublicName("Runtime-Info.plist")
-                .setCategory(I18N.getString("resource.runtime-info-plist"))
-                .setSubstitutionData(data)
-                .saveToFile(file);
-    }
-
-    private void writeInfoPlist(File file, Map<String, ? super Object> params)
-            throws IOException {
-        Log.verbose(MessageFormat.format(I18N.getString(
-                "message.preparing-info-plist"), file.getAbsolutePath()));
-
-        //prepare config for exe
-        //Note: do not need CFBundleDisplayName if we don't support localization
-        Map<String, String> data = new HashMap<>();
-        data.put("DEPLOY_ICON_FILE", APP_NAME.fetchFrom(params) + ".icns");
-        data.put("DEPLOY_BUNDLE_IDENTIFIER",
-                MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params));
-        data.put("DEPLOY_BUNDLE_NAME",
-                getBundleName(params));
-        data.put("DEPLOY_BUNDLE_COPYRIGHT",
-                COPYRIGHT.fetchFrom(params) != null ?
-                COPYRIGHT.fetchFrom(params) : "Unknown");
-        data.put("DEPLOY_LAUNCHER_NAME", getLauncherName(params));
-        data.put("DEPLOY_BUNDLE_SHORT_VERSION",
-                VERSION.fetchFrom(params) != null ?
-                VERSION.fetchFrom(params) : "1.0.0");
-        data.put("DEPLOY_BUNDLE_CFBUNDLE_VERSION",
-                MAC_CF_BUNDLE_VERSION.fetchFrom(params) != null ?
-                MAC_CF_BUNDLE_VERSION.fetchFrom(params) : "100");
-
-        boolean hasMainJar = MAIN_JAR.fetchFrom(params) != null;
-        boolean hasMainModule =
-                StandardBundlerParam.MODULE.fetchFrom(params) != null;
-
-        if (hasMainJar) {
-            data.put("DEPLOY_MAIN_JAR_NAME", MAIN_JAR.fetchFrom(params).
-                    getIncludedFiles().iterator().next());
-        }
-        else if (hasMainModule) {
-            data.put("DEPLOY_MODULE_NAME",
-                    StandardBundlerParam.MODULE.fetchFrom(params));
-        }
-
-        StringBuilder sb = new StringBuilder();
-        List<String> jvmOptions = JAVA_OPTIONS.fetchFrom(params);
-
-        String newline = ""; //So we don't add extra line after last append
-        for (String o : jvmOptions) {
-            sb.append(newline).append(
-                    "    <string>").append(o).append("</string>");
-            newline = "\n";
-        }
-
-        data.put("DEPLOY_JAVA_OPTIONS", sb.toString());
-
-        sb = new StringBuilder();
-        List<String> args = ARGUMENTS.fetchFrom(params);
-        newline = "";
-        // So we don't add unneccessary extra line after last append
-
-        for (String o : args) {
-            sb.append(newline).append("    <string>").append(o).append(
-                    "</string>");
-            newline = "\n";
-        }
-        data.put("DEPLOY_ARGUMENTS", sb.toString());
-
-        newline = "";
-
-        data.put("DEPLOY_LAUNCHER_CLASS", MAIN_CLASS.fetchFrom(params));
-
-        data.put("DEPLOY_APP_CLASSPATH",
-                  getCfgClassPath(CLASSPATH.fetchFrom(params)));
-
-        StringBuilder bundleDocumentTypes = new StringBuilder();
-        StringBuilder exportedTypes = new StringBuilder();
-        for (Map<String, ? super Object>
-                fileAssociation : FILE_ASSOCIATIONS.fetchFrom(params)) {
-
-            List<String> extensions = FA_EXTENSIONS.fetchFrom(fileAssociation);
-
-            if (extensions == null) {
-                Log.verbose(I18N.getString(
-                        "message.creating-association-with-null-extension"));
-            }
-
-            List<String> mimeTypes = FA_CONTENT_TYPE.fetchFrom(fileAssociation);
-            String itemContentType = MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params)
-                    + "." + ((extensions == null || extensions.isEmpty())
-                    ? "mime" : extensions.get(0));
-            String description = FA_DESCRIPTION.fetchFrom(fileAssociation);
-            File icon = FA_ICON.fetchFrom(fileAssociation);
-
-            bundleDocumentTypes.append("    <dict>\n")
-                    .append("      <key>LSItemContentTypes</key>\n")
-                    .append("      <array>\n")
-                    .append("        <string>")
-                    .append(itemContentType)
-                    .append("</string>\n")
-                    .append("      </array>\n")
-                    .append("\n")
-                    .append("      <key>CFBundleTypeName</key>\n")
-                    .append("      <string>")
-                    .append(description)
-                    .append("</string>\n")
-                    .append("\n")
-                    .append("      <key>LSHandlerRank</key>\n")
-                    .append("      <string>Owner</string>\n")
-                            // TODO make a bundler arg
-                    .append("\n")
-                    .append("      <key>CFBundleTypeRole</key>\n")
-                    .append("      <string>Editor</string>\n")
-                            // TODO make a bundler arg
-                    .append("\n")
-                    .append("      <key>LSIsAppleDefaultForType</key>\n")
-                    .append("      <true/>\n")
-                            // TODO make a bundler arg
-                    .append("\n");
-
-            if (icon != null && icon.exists()) {
-                bundleDocumentTypes
-                        .append("      <key>CFBundleTypeIconFile</key>\n")
-                        .append("      <string>")
-                        .append(icon.getName())
-                        .append("</string>\n");
-            }
-            bundleDocumentTypes.append("    </dict>\n");
-
-            exportedTypes.append("    <dict>\n")
-                    .append("      <key>UTTypeIdentifier</key>\n")
-                    .append("      <string>")
-                    .append(itemContentType)
-                    .append("</string>\n")
-                    .append("\n")
-                    .append("      <key>UTTypeDescription</key>\n")
-                    .append("      <string>")
-                    .append(description)
-                    .append("</string>\n")
-                    .append("      <key>UTTypeConformsTo</key>\n")
-                    .append("      <array>\n")
-                    .append("          <string>public.data</string>\n")
-                            //TODO expose this?
-                    .append("      </array>\n")
-                    .append("\n");
-
-            if (icon != null && icon.exists()) {
-                exportedTypes.append("      <key>UTTypeIconFile</key>\n")
-                        .append("      <string>")
-                        .append(icon.getName())
-                        .append("</string>\n")
-                        .append("\n");
-            }
-
-            exportedTypes.append("\n")
-                    .append("      <key>UTTypeTagSpecification</key>\n")
-                    .append("      <dict>\n")
-                            // TODO expose via param? .append(
-                            // "        <key>com.apple.ostype</key>\n");
-                            // TODO expose via param? .append(
-                            // "        <string>ABCD</string>\n")
-                    .append("\n");
-
-            if (extensions != null && !extensions.isEmpty()) {
-                exportedTypes.append(
-                        "        <key>public.filename-extension</key>\n")
-                        .append("        <array>\n");
-
-                for (String ext : extensions) {
-                    exportedTypes.append("          <string>")
-                            .append(ext)
-                            .append("</string>\n");
-                }
-                exportedTypes.append("        </array>\n");
-            }
-            if (mimeTypes != null && !mimeTypes.isEmpty()) {
-                exportedTypes.append("        <key>public.mime-type</key>\n")
-                        .append("        <array>\n");
-
-                for (String mime : mimeTypes) {
-                    exportedTypes.append("          <string>")
-                            .append(mime)
-                            .append("</string>\n");
-                }
-                exportedTypes.append("        </array>\n");
-            }
-            exportedTypes.append("      </dict>\n")
-                    .append("    </dict>\n");
-        }
-        String associationData;
-        if (bundleDocumentTypes.length() > 0) {
-            associationData =
-                    "\n  <key>CFBundleDocumentTypes</key>\n  <array>\n"
-                    + bundleDocumentTypes.toString()
-                    + "  </array>\n\n"
-                    + "  <key>UTExportedTypeDeclarations</key>\n  <array>\n"
-                    + exportedTypes.toString()
-                    + "  </array>\n";
-        } else {
-            associationData = "";
-        }
-        data.put("DEPLOY_FILE_ASSOCIATIONS", associationData);
-
-        createResource(TEMPLATE_INFO_PLIST_LITE, params)
-                .setCategory(I18N.getString("resource.app-info-plist"))
-                .setSubstitutionData(data)
-                .setPublicName("Info.plist")
-                .saveToFile(file);
-    }
-
-    private void writePkgInfo(File file) throws IOException {
-        //hardcoded as it does not seem we need to change it ever
-        String signature = "????";
-
-        try (Writer out = Files.newBufferedWriter(file.toPath())) {
-            out.write(OS_TYPE_CODE + signature);
-            out.flush();
-        }
-    }
-
-    public static void addNewKeychain(Map<String, ? super Object> params)
-                                    throws IOException, InterruptedException {
-        if (Platform.getMajorVersion() < 10 ||
-                (Platform.getMajorVersion() == 10 &&
-                Platform.getMinorVersion() < 12)) {
-            // we need this for OS X 10.12+
-            return;
-        }
-
-        String keyChain = SIGNING_KEYCHAIN.fetchFrom(params);
-        if (keyChain == null || keyChain.isEmpty()) {
-            return;
-        }
-
-        // get current keychain list
-        String keyChainPath = new File (keyChain).getAbsolutePath().toString();
-        List<String> keychainList = new ArrayList<>();
-        int ret = IOUtils.getProcessOutput(
-                keychainList, "security", "list-keychains");
-        if (ret != 0) {
-            Log.error(I18N.getString("message.keychain.error"));
-            return;
-        }
-
-        boolean contains = keychainList.stream().anyMatch(
-                    str -> str.trim().equals("\""+keyChainPath.trim()+"\""));
-        if (contains) {
-            // keychain is already added in the search list
-            return;
-        }
-
-        keyChains = new ArrayList<>();
-        // remove "
-        keychainList.forEach((String s) -> {
-            String path = s.trim();
-            if (path.startsWith("\"") && path.endsWith("\"")) {
-                path = path.substring(1, path.length()-1);
-            }
-            keyChains.add(path);
-        });
-
-        List<String> args = new ArrayList<>();
-        args.add("security");
-        args.add("list-keychains");
-        args.add("-s");
-
-        args.addAll(keyChains);
-        args.add(keyChain);
-
-        ProcessBuilder  pb = new ProcessBuilder(args);
-        IOUtils.exec(pb);
-    }
-
-    public static void restoreKeychainList(Map<String, ? super Object> params)
-            throws IOException{
-        if (Platform.getMajorVersion() < 10 ||
-                (Platform.getMajorVersion() == 10 &&
-                Platform.getMinorVersion() < 12)) {
-            // we need this for OS X 10.12+
-            return;
-        }
-
-        if (keyChains == null || keyChains.isEmpty()) {
-            return;
-        }
-
-        List<String> args = new ArrayList<>();
-        args.add("security");
-        args.add("list-keychains");
-        args.add("-s");
-
-        args.addAll(keyChains);
-
-        ProcessBuilder  pb = new ProcessBuilder(args);
-        IOUtils.exec(pb);
-    }
-
-    public static void signAppBundle(
-            Map<String, ? super Object> params, Path appLocation,
-            String signingIdentity, String identifierPrefix,
-            String entitlementsFile, String inheritedEntitlements)
-            throws IOException {
-        AtomicReference<IOException> toThrow = new AtomicReference<>();
-        String appExecutable = "/Contents/MacOS/" + APP_NAME.fetchFrom(params);
-        String keyChain = SIGNING_KEYCHAIN.fetchFrom(params);
-
-        // sign all dylibs and jars
-        try (Stream<Path> stream = Files.walk(appLocation)) {
-            stream.peek(path -> { // fix permissions
-                try {
-                    Set<PosixFilePermission> pfp =
-                            Files.getPosixFilePermissions(path);
-                    if (!pfp.contains(PosixFilePermission.OWNER_WRITE)) {
-                        pfp = EnumSet.copyOf(pfp);
-                        pfp.add(PosixFilePermission.OWNER_WRITE);
-                        Files.setPosixFilePermissions(path, pfp);
-                    }
-                } catch (IOException e) {
-                    Log.verbose(e);
-                }
-            }).filter(p -> Files.isRegularFile(p)
-                      && !(p.toString().contains("/Contents/MacOS/libjli.dylib")
-                      || p.toString().endsWith(appExecutable)
-                      || p.toString().contains("/Contents/runtime")
-                      || p.toString().contains("/Contents/Frameworks"))).forEach(p -> {
-                //noinspection ThrowableResultOfMethodCallIgnored
-                if (toThrow.get() != null) return;
-
-                // If p is a symlink then skip the signing process.
-                if (Files.isSymbolicLink(p)) {
-                    if (VERBOSE.fetchFrom(params)) {
-                        Log.verbose(MessageFormat.format(I18N.getString(
-                                "message.ignoring.symlink"), p.toString()));
-                    }
-                } else {
-                    if (p.toString().endsWith(LIBRARY_NAME)) {
-                        if (isFileSigned(p)) {
-                            return;
-                        }
-                    }
-
-                    List<String> args = new ArrayList<>();
-                    args.addAll(Arrays.asList("codesign",
-                            "-s", signingIdentity, // sign with this key
-                            "--prefix", identifierPrefix,
-                            // use the identifier as a prefix
-                            "-vvvv"));
-                    if (entitlementsFile != null &&
-                            (p.toString().endsWith(".jar")
-                            || p.toString().endsWith(".dylib"))) {
-                        args.add("--entitlements");
-                        args.add(entitlementsFile); // entitlements
-                    } else if (inheritedEntitlements != null &&
-                            Files.isExecutable(p)) {
-                        args.add("--entitlements");
-                        args.add(inheritedEntitlements);
-                        // inherited entitlements for executable processes
-                    }
-                    if (keyChain != null && !keyChain.isEmpty()) {
-                        args.add("--keychain");
-                        args.add(keyChain);
-                    }
-                    args.add(p.toString());
-
-                    try {
-                        Set<PosixFilePermission> oldPermissions =
-                                Files.getPosixFilePermissions(p);
-                        File f = p.toFile();
-                        f.setWritable(true, true);
-
-                        ProcessBuilder pb = new ProcessBuilder(args);
-                        IOUtils.exec(pb);
-
-                        Files.setPosixFilePermissions(p, oldPermissions);
-                    } catch (IOException ioe) {
-                        toThrow.set(ioe);
-                    }
-                }
-            });
-        }
-        IOException ioe = toThrow.get();
-        if (ioe != null) {
-            throw ioe;
-        }
-
-        // sign all runtime and frameworks
-        Consumer<? super Path> signIdentifiedByPList = path -> {
-            //noinspection ThrowableResultOfMethodCallIgnored
-            if (toThrow.get() != null) return;
-
-            try {
-                List<String> args = new ArrayList<>();
-                args.addAll(Arrays.asList("codesign",
-                        "-s", signingIdentity, // sign with this key
-                        "--prefix", identifierPrefix,
-                        // use the identifier as a prefix
-                        "-vvvv"));
-                if (keyChain != null && !keyChain.isEmpty()) {
-                    args.add("--keychain");
-                    args.add(keyChain);
-                }
-                args.add(path.toString());
-                ProcessBuilder pb = new ProcessBuilder(args);
-                IOUtils.exec(pb);
-
-                args = new ArrayList<>();
-                args.addAll(Arrays.asList("codesign",
-                        "-s", signingIdentity, // sign with this key
-                        "--prefix", identifierPrefix,
-                        // use the identifier as a prefix
-                        "-vvvv"));
-                if (keyChain != null && !keyChain.isEmpty()) {
-                    args.add("--keychain");
-                    args.add(keyChain);
-                }
-                args.add(path.toString()
-                        + "/Contents/_CodeSignature/CodeResources");
-                pb = new ProcessBuilder(args);
-                IOUtils.exec(pb);
-            } catch (IOException e) {
-                toThrow.set(e);
-            }
-        };
-
-        Path javaPath = appLocation.resolve("Contents/runtime");
-        if (Files.isDirectory(javaPath)) {
-            signIdentifiedByPList.accept(javaPath);
-
-            ioe = toThrow.get();
-            if (ioe != null) {
-                throw ioe;
-            }
-        }
-        Path frameworkPath = appLocation.resolve("Contents/Frameworks");
-        if (Files.isDirectory(frameworkPath)) {
-            Files.list(frameworkPath)
-                    .forEach(signIdentifiedByPList);
-
-            ioe = toThrow.get();
-            if (ioe != null) {
-                throw ioe;
-            }
-        }
-
-        // sign the app itself
-        List<String> args = new ArrayList<>();
-        args.addAll(Arrays.asList("codesign",
-                "-s", signingIdentity, // sign with this key
-                "-vvvv")); // super verbose output
-        if (entitlementsFile != null) {
-            args.add("--entitlements");
-            args.add(entitlementsFile); // entitlements
-        }
-        if (keyChain != null && !keyChain.isEmpty()) {
-            args.add("--keychain");
-            args.add(keyChain);
-        }
-        args.add(appLocation.toString());
-
-        ProcessBuilder pb =
-                new ProcessBuilder(args.toArray(new String[args.size()]));
-        IOUtils.exec(pb);
-    }
-
-    private static boolean isFileSigned(Path file) {
-        ProcessBuilder pb =
-                new ProcessBuilder("codesign", "--verify", file.toString());
-
-        try {
-            IOUtils.exec(pb);
-        } catch (IOException ex) {
-            return false;
-        }
-
-        return true;
-    }
-
-    private static String extractBundleIdentifier(Map<String, Object> params) {
-        if (PREDEFINED_APP_IMAGE.fetchFrom(params) == null) {
-            return null;
-        }
-
-        try {
-            File infoPList = new File(PREDEFINED_APP_IMAGE.fetchFrom(params) +
-                                      File.separator + "Contents" +
-                                      File.separator + "Info.plist");
-
-            DocumentBuilderFactory dbf
-                    = DocumentBuilderFactory.newDefaultInstance();
-            dbf.setFeature("http://apache.org/xml/features/" +
-                           "nonvalidating/load-external-dtd", false);
-            DocumentBuilder b = dbf.newDocumentBuilder();
-            org.w3c.dom.Document doc = b.parse(new FileInputStream(
-                    infoPList.getAbsolutePath()));
-
-            XPath xPath = XPathFactory.newInstance().newXPath();
-            // Query for the value of <string> element preceding <key>
-            // element with value equal to CFBundleIdentifier
-            String v = (String) xPath.evaluate(
-                    "//string[preceding-sibling::key = \"CFBundleIdentifier\"][1]",
-                    doc, XPathConstants.STRING);
-
-            if (v != null && !v.isEmpty()) {
-                return v;
-            }
-        } catch (Exception ex) {
-            Log.verbose(ex);
-        }
-
-        return null;
-    }
-
-}
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppStoreBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.File;
-import java.io.IOException;
-import java.text.MessageFormat;
-import java.util.*;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-import static jdk.jpackage.internal.MacAppBundler.*;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-
-public class MacAppStoreBundler extends MacBaseInstallerBundler {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MacResources");
-
-    private static final String TEMPLATE_BUNDLE_ICON_HIDPI = "java.icns";
-    private final static String DEFAULT_ENTITLEMENTS =
-            "MacAppStore.entitlements";
-    private final static String DEFAULT_INHERIT_ENTITLEMENTS =
-            "MacAppStore_Inherit.entitlements";
-
-    public static final BundlerParamInfo<String> MAC_APP_STORE_APP_SIGNING_KEY =
-            new StandardBundlerParam<>(
-            "mac.signing-key-app",
-            String.class,
-            params -> {
-                String result = MacBaseInstallerBundler.findKey(
-                        "3rd Party Mac Developer Application: " +
-                        SIGNING_KEY_USER.fetchFrom(params),
-                        SIGNING_KEYCHAIN.fetchFrom(params),
-                        VERBOSE.fetchFrom(params));
-                if (result != null) {
-                    MacCertificate certificate = new MacCertificate(result);
-
-                    if (!certificate.isValid()) {
-                        Log.error(MessageFormat.format(
-                                I18N.getString("error.certificate.expired"),
-                                result));
-                    }
-                }
-
-                return result;
-            },
-            (s, p) -> s);
-
-    public static final BundlerParamInfo<String> MAC_APP_STORE_PKG_SIGNING_KEY =
-            new StandardBundlerParam<>(
-            "mac.signing-key-pkg",
-            String.class,
-            params -> {
-                String result = MacBaseInstallerBundler.findKey(
-                        "3rd Party Mac Developer Installer: " +
-                        SIGNING_KEY_USER.fetchFrom(params),
-                        SIGNING_KEYCHAIN.fetchFrom(params),
-                        VERBOSE.fetchFrom(params));
-
-                if (result != null) {
-                    MacCertificate certificate = new MacCertificate(result);
-
-                    if (!certificate.isValid()) {
-                        Log.error(MessageFormat.format(
-                                I18N.getString("error.certificate.expired"),
-                                result));
-                    }
-                }
-
-                return result;
-            },
-            (s, p) -> s);
-
-    public static final StandardBundlerParam<File> MAC_APP_STORE_ENTITLEMENTS  =
-            new StandardBundlerParam<>(
-            Arguments.CLIOptions.MAC_APP_STORE_ENTITLEMENTS.getId(),
-            File.class,
-            params -> null,
-            (s, p) -> new File(s));
-
-    public static final BundlerParamInfo<String> INSTALLER_SUFFIX =
-            new StandardBundlerParam<> (
-            "mac.app-store.installerName.suffix",
-            String.class,
-            params -> "-MacAppStore",
-            (s, p) -> s);
-
-    public File bundle(Map<String, ? super Object> params,
-            File outdir) throws PackagerException {
-        Log.verbose(MessageFormat.format(I18N.getString(
-                "message.building-bundle"), APP_NAME.fetchFrom(params)));
-
-        IOUtils.writableOutputDir(outdir.toPath());
-
-        // first, load in some overrides
-        // icns needs @2 versions, so load in the @2 default
-        params.put(DEFAULT_ICNS_ICON.getID(), TEMPLATE_BUNDLE_ICON_HIDPI);
-
-        // now we create the app
-        File appImageDir = APP_IMAGE_TEMP_ROOT.fetchFrom(params);
-        try {
-            appImageDir.mkdirs();
-
-            try {
-                MacAppImageBuilder.addNewKeychain(params);
-            } catch (InterruptedException e) {
-                Log.error(e.getMessage());
-            }
-            // first, make sure we don't use the local signing key
-            params.put(DEVELOPER_ID_APP_SIGNING_KEY.getID(), null);
-            File appLocation = prepareAppBundle(params);
-
-            prepareEntitlements(params);
-
-            String signingIdentity =
-                    MAC_APP_STORE_APP_SIGNING_KEY.fetchFrom(params);
-            String identifierPrefix =
-                    BUNDLE_ID_SIGNING_PREFIX.fetchFrom(params);
-            String entitlementsFile =
-                    getConfig_Entitlements(params).toString();
-            String inheritEntitlements =
-                    getConfig_Inherit_Entitlements(params).toString();
-
-            MacAppImageBuilder.signAppBundle(params, appLocation.toPath(),
-                    signingIdentity, identifierPrefix,
-                    entitlementsFile, inheritEntitlements);
-            MacAppImageBuilder.restoreKeychainList(params);
-
-            ProcessBuilder pb;
-
-            // create the final pkg file
-            File finalPKG = new File(outdir, INSTALLER_NAME.fetchFrom(params)
-                    + INSTALLER_SUFFIX.fetchFrom(params)
-                    + ".pkg");
-            outdir.mkdirs();
-
-            String installIdentify =
-                    MAC_APP_STORE_PKG_SIGNING_KEY.fetchFrom(params);
-
-            List<String> buildOptions = new ArrayList<>();
-            buildOptions.add("productbuild");
-            buildOptions.add("--component");
-            buildOptions.add(appLocation.toString());
-            buildOptions.add("/Applications");
-            buildOptions.add("--sign");
-            buildOptions.add(installIdentify);
-            buildOptions.add("--product");
-            buildOptions.add(appLocation + "/Contents/Info.plist");
-            String keychainName = SIGNING_KEYCHAIN.fetchFrom(params);
-            if (keychainName != null && !keychainName.isEmpty()) {
-                buildOptions.add("--keychain");
-                buildOptions.add(keychainName);
-            }
-            buildOptions.add(finalPKG.getAbsolutePath());
-
-            pb = new ProcessBuilder(buildOptions);
-
-            IOUtils.exec(pb);
-            return finalPKG;
-        } catch (PackagerException pe) {
-            throw pe;
-        } catch (Exception ex) {
-            Log.verbose(ex);
-            throw new PackagerException(ex);
-        }
-    }
-
-    private File getConfig_Entitlements(Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + ".entitlements");
-    }
-
-    private File getConfig_Inherit_Entitlements(
-            Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + "_Inherit.entitlements");
-    }
-
-    private void prepareEntitlements(Map<String, ? super Object> params)
-            throws IOException {
-        createResource(DEFAULT_ENTITLEMENTS, params)
-                .setCategory(
-                        I18N.getString("resource.mac-app-store-entitlements"))
-                .setExternal(MAC_APP_STORE_ENTITLEMENTS.fetchFrom(params))
-                .saveToFile(getConfig_Entitlements(params));
-
-        createResource(DEFAULT_INHERIT_ENTITLEMENTS, params)
-                .setCategory(I18N.getString(
-                        "resource.mac-app-store-inherit-entitlements"))
-                .saveToFile(getConfig_Entitlements(params));
-    }
-
-    ///////////////////////////////////////////////////////////////////////
-    // Implement Bundler
-    ///////////////////////////////////////////////////////////////////////
-
-    @Override
-    public String getName() {
-        return I18N.getString("store.bundler.name");
-    }
-
-    @Override
-    public String getID() {
-        return "mac.appStore";
-    }
-
-    @Override
-    public boolean validate(Map<String, ? super Object> params)
-            throws ConfigException {
-        try {
-            Objects.requireNonNull(params);
-
-            // hdiutil is always available so there's no need to test for
-            // availability.
-            // run basic validation to ensure requirements are met
-
-            // we are not interested in return code, only possible exception
-            validateAppImageAndBundeler(params);
-
-            // reject explicitly set to not sign
-            if (!Optional.ofNullable(MacAppImageBuilder.
-                    SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) {
-                throw new ConfigException(
-                        I18N.getString("error.must-sign-app-store"),
-                        I18N.getString("error.must-sign-app-store.advice"));
-            }
-
-            // make sure we have settings for signatures
-            if (MAC_APP_STORE_APP_SIGNING_KEY.fetchFrom(params) == null) {
-                throw new ConfigException(
-                        I18N.getString("error.no-app-signing-key"),
-                        I18N.getString("error.no-app-signing-key.advice"));
-            }
-            if (MAC_APP_STORE_PKG_SIGNING_KEY.fetchFrom(params) == null) {
-                throw new ConfigException(
-                        I18N.getString("error.no-pkg-signing-key"),
-                        I18N.getString("error.no-pkg-signing-key.advice"));
-            }
-
-            // things we could check...
-            // check the icons, make sure it has hidpi icons
-            // check the category,
-            // make sure it fits in the list apple has provided
-            // validate bundle identifier is reverse dns
-            // check for \a+\.\a+\..
-
-            return true;
-        } catch (RuntimeException re) {
-            if (re.getCause() instanceof ConfigException) {
-                throw (ConfigException) re.getCause();
-            } else {
-                throw new ConfigException(re);
-            }
-        }
-    }
-
-    @Override
-    public File execute(Map<String, ? super Object> params,
-            File outputParentDir) throws PackagerException {
-        return bundle(params, outputParentDir);
-    }
-
-    @Override
-    public boolean supported(boolean runtimeInstaller) {
-        // return (!runtimeInstaller &&
-        //         Platform.getPlatform() == Platform.MAC);
-        return false; // mac-app-store not yet supported
-    }
-
-    @Override
-    public boolean isDefault() {
-        return false;
-    }
-
-}
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.nio.file.Files;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.ResourceBundle;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-public abstract class MacBaseInstallerBundler extends AbstractBundler {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MacResources");
-
-    // This could be generalized more to be for any type of Image Bundler
-    public static final BundlerParamInfo<MacAppBundler> APP_BUNDLER =
-            new StandardBundlerParam<>(
-            "mac.app.bundler",
-            MacAppBundler.class,
-            params -> new MacAppBundler(),
-            (s, p) -> null);
-
-    public final BundlerParamInfo<File> APP_IMAGE_TEMP_ROOT =
-            new StandardBundlerParam<>(
-            "mac.app.imageRoot",
-            File.class,
-            params -> {
-                File imageDir = IMAGES_ROOT.fetchFrom(params);
-                if (!imageDir.exists()) imageDir.mkdirs();
-                try {
-                    return Files.createTempDirectory(
-                            imageDir.toPath(), "image-").toFile();
-                } catch (IOException e) {
-                    return new File(imageDir, getID()+ ".image");
-                }
-            },
-            (s, p) -> new File(s));
-
-    public static final BundlerParamInfo<String> SIGNING_KEY_USER =
-            new StandardBundlerParam<>(
-            Arguments.CLIOptions.MAC_SIGNING_KEY_NAME.getId(),
-            String.class,
-            params -> "",
-            null);
-
-    public static final BundlerParamInfo<String> SIGNING_KEYCHAIN =
-            new StandardBundlerParam<>(
-            Arguments.CLIOptions.MAC_SIGNING_KEYCHAIN.getId(),
-            String.class,
-            params -> "",
-            null);
-
-    public static final BundlerParamInfo<String> INSTALLER_NAME =
-            new StandardBundlerParam<> (
-            "mac.installerName",
-            String.class,
-            params -> {
-                String nm = APP_NAME.fetchFrom(params);
-                if (nm == null) return null;
-
-                String version = VERSION.fetchFrom(params);
-                if (version == null) {
-                    return nm;
-                } else {
-                    return nm + "-" + version;
-                }
-            },
-            (s, p) -> s);
-
-    protected void validateAppImageAndBundeler(
-            Map<String, ? super Object> params) throws ConfigException {
-        if (PREDEFINED_APP_IMAGE.fetchFrom(params) != null) {
-            File applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params);
-            if (!applicationImage.exists()) {
-                throw new ConfigException(
-                        MessageFormat.format(I18N.getString(
-                                "message.app-image-dir-does-not-exist"),
-                                PREDEFINED_APP_IMAGE.getID(),
-                                applicationImage.toString()),
-                        MessageFormat.format(I18N.getString(
-                                "message.app-image-dir-does-not-exist.advice"),
-                                PREDEFINED_APP_IMAGE.getID()));
-            }
-            if (APP_NAME.fetchFrom(params) == null) {
-                throw new ConfigException(
-                        I18N.getString("message.app-image-requires-app-name"),
-                        I18N.getString(
-                            "message.app-image-requires-app-name.advice"));
-            }
-        } else {
-            APP_BUNDLER.fetchFrom(params).validate(params);
-        }
-    }
-
-    protected File prepareAppBundle(Map<String, ? super Object> params)
-            throws PackagerException {
-        File predefinedImage =
-                StandardBundlerParam.getPredefinedAppImage(params);
-        if (predefinedImage != null) {
-            return predefinedImage;
-        }
-        File appImageRoot = APP_IMAGE_TEMP_ROOT.fetchFrom(params);
-
-        return APP_BUNDLER.fetchFrom(params).doBundle(
-                params, appImageRoot, true);
-    }
-
-    @Override
-    public String getBundleType() {
-        return "INSTALLER";
-    }
-
-    public static String findKey(String key, String keychainName,
-            boolean verbose) {
-        if (Platform.getPlatform() != Platform.MAC) {
-            return null;
-        }
-
-        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                PrintStream ps = new PrintStream(baos)) {
-            List<String> searchOptions = new ArrayList<>();
-            searchOptions.add("security");
-            searchOptions.add("find-certificate");
-            searchOptions.add("-c");
-            searchOptions.add(key);
-            searchOptions.add("-a");
-            if (keychainName != null && !keychainName.isEmpty()) {
-                searchOptions.add(keychainName);
-            }
-
-            ProcessBuilder pb = new ProcessBuilder(searchOptions);
-
-            IOUtils.exec(pb, false, ps);
-            Pattern p = Pattern.compile("\"alis\"<blob>=\"([^\"]+)\"");
-            Matcher m = p.matcher(baos.toString());
-            if (!m.find()) {
-                Log.error("Did not find a key matching '" + key + "'");
-                return null;
-            }
-            String matchedKey = m.group(1);
-            if (m.find()) {
-                Log.error("Found more than one key matching '"  + key + "'");
-                return null;
-            }
-            Log.verbose("Using key '" + matchedKey + "'");
-            return matchedKey;
-        } catch (IOException ioe) {
-            Log.verbose(ioe);
-            return null;
-        }
-    }
-}
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacCertificate.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2016, 2019, 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.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.nio.file.StandardCopyOption;
-import java.nio.file.Files;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-
-public final class MacCertificate {
-    private final String certificate;
-
-    public MacCertificate(String certificate) {
-        this.certificate = certificate;
-    }
-
-    public boolean isValid() {
-        return verifyCertificate(this.certificate);
-    }
-
-    private static File findCertificate(String certificate) {
-        File result = null;
-
-        List<String> args = new ArrayList<>();
-        args.add("security");
-        args.add("find-certificate");
-        args.add("-c");
-        args.add(certificate);
-        args.add("-a");
-        args.add("-p");
-
-        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                PrintStream ps = new PrintStream(baos)) {
-            ProcessBuilder security = new ProcessBuilder(args);
-            IOUtils.exec(security, false, ps);
-
-            File output = File.createTempFile("tempfile", ".tmp");
-
-            Files.copy(new ByteArrayInputStream(baos.toByteArray()),
-                    output.toPath(), StandardCopyOption.REPLACE_EXISTING);
-
-            result = output;
-        }
-        catch (IOException ignored) {}
-
-        return result;
-    }
-
-    private static Date findCertificateDate(String filename) {
-        Date result = null;
-
-        List<String> args = new ArrayList<>();
-        args.add("/usr/bin/openssl");
-        args.add("x509");
-        args.add("-noout");
-        args.add("-enddate");
-        args.add("-in");
-        args.add(filename);
-
-        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                PrintStream ps = new PrintStream(baos)) {
-            ProcessBuilder security = new ProcessBuilder(args);
-            IOUtils.exec(security, false, ps);
-            String output = baos.toString();
-            output = output.substring(output.indexOf("=") + 1);
-            DateFormat df = new SimpleDateFormat(
-                    "MMM dd kk:mm:ss yyyy z", Locale.ENGLISH);
-            result = df.parse(output);
-        } catch (IOException | ParseException ex) {
-            Log.verbose(ex);
-        }
-
-        return result;
-    }
-
-    private static boolean verifyCertificate(String certificate) {
-        boolean result = false;
-
-        try {
-            File file = null;
-            Date certificateDate = null;
-
-            try {
-                file = findCertificate(certificate);
-
-                if (file != null) {
-                    certificateDate = findCertificateDate(
-                            file.getCanonicalPath());
-                }
-            }
-            finally {
-                if (file != null) {
-                    file.delete();
-                }
-            }
-
-            if (certificateDate != null) {
-                Calendar c = Calendar.getInstance();
-                Date today = c.getTime();
-
-                if (certificateDate.after(today)) {
-                    result = true;
-                }
-            }
-        }
-        catch (IOException ignored) {}
-
-        return result;
-    }
-}
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacDmgBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,480 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.*;
-import java.nio.file.Files;
-import java.text.MessageFormat;
-import java.util.*;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-public class MacDmgBundler extends MacBaseInstallerBundler {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MacResources");
-
-    static final String DEFAULT_BACKGROUND_IMAGE="background_dmg.png";
-    static final String DEFAULT_DMG_SETUP_SCRIPT="DMGsetup.scpt";
-    static final String TEMPLATE_BUNDLE_ICON = "java.icns";
-
-    static final String DEFAULT_LICENSE_PLIST="lic_template.plist";
-
-    public static final BundlerParamInfo<String> INSTALLER_SUFFIX =
-            new StandardBundlerParam<> (
-            "mac.dmg.installerName.suffix",
-            String.class,
-            params -> "",
-            (s, p) -> s);
-
-    public File bundle(Map<String, ? super Object> params,
-            File outdir) throws PackagerException {
-        Log.verbose(MessageFormat.format(I18N.getString("message.building-dmg"),
-                APP_NAME.fetchFrom(params)));
-
-        IOUtils.writableOutputDir(outdir.toPath());
-
-        File appImageDir = APP_IMAGE_TEMP_ROOT.fetchFrom(params);
-        try {
-            appImageDir.mkdirs();
-
-            if (prepareAppBundle(params) != null &&
-                    prepareConfigFiles(params)) {
-                File configScript = getConfig_Script(params);
-                if (configScript.exists()) {
-                    Log.verbose(MessageFormat.format(
-                            I18N.getString("message.running-script"),
-                            configScript.getAbsolutePath()));
-                    IOUtils.run("bash", configScript);
-                }
-
-                return buildDMG(params, outdir);
-            }
-            return null;
-        } catch (IOException ex) {
-            Log.verbose(ex);
-            throw new PackagerException(ex);
-        }
-    }
-
-    private static final String hdiutil = "/usr/bin/hdiutil";
-
-    private void prepareDMGSetupScript(String volumeName,
-            Map<String, ? super Object> params) throws IOException {
-        File dmgSetup = getConfig_VolumeScript(params);
-        Log.verbose(MessageFormat.format(
-                I18N.getString("message.preparing-dmg-setup"),
-                dmgSetup.getAbsolutePath()));
-
-        //prepare config for exe
-        Map<String, String> data = new HashMap<>();
-        data.put("DEPLOY_ACTUAL_VOLUME_NAME", volumeName);
-        data.put("DEPLOY_APPLICATION_NAME", APP_NAME.fetchFrom(params));
-
-        data.put("DEPLOY_INSTALL_LOCATION", "(path to applications folder)");
-        data.put("DEPLOY_INSTALL_NAME", "Applications");
-
-        createResource(DEFAULT_DMG_SETUP_SCRIPT, params)
-                .setCategory(I18N.getString("resource.dmg-setup-script"))
-                .setSubstitutionData(data)
-                .saveToFile(dmgSetup);
-    }
-
-    private File getConfig_VolumeScript(Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + "-dmg-setup.scpt");
-    }
-
-    private File getConfig_VolumeBackground(
-            Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + "-background.png");
-    }
-
-    private File getConfig_VolumeIcon(Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + "-volume.icns");
-    }
-
-    private File getConfig_LicenseFile(Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + "-license.plist");
-    }
-
-    private void prepareLicense(Map<String, ? super Object> params) {
-        try {
-            String licFileStr = LICENSE_FILE.fetchFrom(params);
-            if (licFileStr == null) {
-                return;
-            }
-
-            File licFile = new File(licFileStr);
-            byte[] licenseContentOriginal =
-                    Files.readAllBytes(licFile.toPath());
-            String licenseInBase64 =
-                    Base64.getEncoder().encodeToString(licenseContentOriginal);
-
-            Map<String, String> data = new HashMap<>();
-            data.put("APPLICATION_LICENSE_TEXT", licenseInBase64);
-
-            createResource(DEFAULT_LICENSE_PLIST, params)
-                    .setCategory(I18N.getString("resource.license-setup"))
-                    .setSubstitutionData(data)
-                    .saveToFile(getConfig_LicenseFile(params));
-
-        } catch (IOException ex) {
-            Log.verbose(ex);
-        }
-    }
-
-    private boolean prepareConfigFiles(Map<String, ? super Object> params)
-            throws IOException {
-
-        createResource(DEFAULT_BACKGROUND_IMAGE, params)
-                    .setCategory(I18N.getString("resource.dmg-background"))
-                    .saveToFile(getConfig_VolumeBackground(params));
-
-        createResource(TEMPLATE_BUNDLE_ICON, params)
-                .setCategory(I18N.getString("resource.volume-icon"))
-                .setExternal(MacAppBundler.ICON_ICNS.fetchFrom(params))
-                .saveToFile(getConfig_VolumeIcon(params));
-
-        createResource(null, params)
-                .setCategory(I18N.getString("resource.post-install-script"))
-                .saveToFile(getConfig_Script(params));
-
-        prepareLicense(params);
-
-        // In theory we need to extract name from results of attach command
-        // However, this will be a problem for customization as name will
-        // possibly change every time and developer will not be able to fix it
-        // As we are using tmp dir chance we get "different" name are low =>
-        // Use fixed name we used for bundle
-        prepareDMGSetupScript(APP_NAME.fetchFrom(params), params);
-
-        return true;
-    }
-
-    // name of post-image script
-    private File getConfig_Script(Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + "-post-image.sh");
-    }
-
-    // Location of SetFile utility may be different depending on MacOS version
-    // We look for several known places and if none of them work will
-    // try ot find it
-    private String findSetFileUtility() {
-        String typicalPaths[] = {"/Developer/Tools/SetFile",
-                "/usr/bin/SetFile", "/Developer/usr/bin/SetFile"};
-
-        String setFilePath = null;
-        for (String path: typicalPaths) {
-            File f = new File(path);
-            if (f.exists() && f.canExecute()) {
-                setFilePath = path;
-                break;
-            }
-        }
-
-        // Validate SetFile, if Xcode is not installed it will run, but exit with error
-        // code
-        if (setFilePath != null) {
-            try {
-                ProcessBuilder pb = new ProcessBuilder(setFilePath, "-h");
-                Process p = pb.start();
-                int code = p.waitFor();
-                if (code == 0) {
-                    return setFilePath;
-                }
-            } catch (Exception ignored) {}
-
-            // No need for generic find attempt. We found it, but it does not work.
-            // Probably due to missing xcode.
-            return null;
-        }
-
-        // generic find attempt
-        try {
-            ProcessBuilder pb = new ProcessBuilder("xcrun", "-find", "SetFile");
-            Process p = pb.start();
-            InputStreamReader isr = new InputStreamReader(p.getInputStream());
-            BufferedReader br = new BufferedReader(isr);
-            String lineRead = br.readLine();
-            if (lineRead != null) {
-                File f = new File(lineRead);
-                if (f.exists() && f.canExecute()) {
-                    return f.getAbsolutePath();
-                }
-            }
-        } catch (IOException ignored) {}
-
-        return null;
-    }
-
-    private File buildDMG(
-            Map<String, ? super Object> params, File outdir)
-            throws IOException {
-        File imagesRoot = IMAGES_ROOT.fetchFrom(params);
-        if (!imagesRoot.exists()) imagesRoot.mkdirs();
-
-        File protoDMG = new File(imagesRoot,
-                APP_NAME.fetchFrom(params) +"-tmp.dmg");
-        File finalDMG = new File(outdir, INSTALLER_NAME.fetchFrom(params)
-                + INSTALLER_SUFFIX.fetchFrom(params) + ".dmg");
-
-        File srcFolder = APP_IMAGE_TEMP_ROOT.fetchFrom(params);
-        File predefinedImage =
-                StandardBundlerParam.getPredefinedAppImage(params);
-        if (predefinedImage != null) {
-            srcFolder = predefinedImage;
-        }
-
-        Log.verbose(MessageFormat.format(I18N.getString(
-                "message.creating-dmg-file"), finalDMG.getAbsolutePath()));
-
-        protoDMG.delete();
-        if (finalDMG.exists() && !finalDMG.delete()) {
-            throw new IOException(MessageFormat.format(I18N.getString(
-                    "message.dmg-cannot-be-overwritten"),
-                    finalDMG.getAbsolutePath()));
-        }
-
-        protoDMG.getParentFile().mkdirs();
-        finalDMG.getParentFile().mkdirs();
-
-        String hdiUtilVerbosityFlag = VERBOSE.fetchFrom(params) ?
-                "-verbose" : "-quiet";
-
-        // create temp image
-        ProcessBuilder pb = new ProcessBuilder(
-                hdiutil,
-                "create",
-                hdiUtilVerbosityFlag,
-                "-srcfolder", srcFolder.getAbsolutePath(),
-                "-volname", APP_NAME.fetchFrom(params),
-                "-ov", protoDMG.getAbsolutePath(),
-                "-fs", "HFS+",
-                "-format", "UDRW");
-        IOUtils.exec(pb);
-
-        // mount temp image
-        pb = new ProcessBuilder(
-                hdiutil,
-                "attach",
-                protoDMG.getAbsolutePath(),
-                hdiUtilVerbosityFlag,
-                "-mountroot", imagesRoot.getAbsolutePath());
-        IOUtils.exec(pb);
-
-        File mountedRoot = new File(imagesRoot.getAbsolutePath(),
-                    APP_NAME.fetchFrom(params));
-
-        try {
-            // volume icon
-            File volumeIconFile = new File(mountedRoot, ".VolumeIcon.icns");
-            IOUtils.copyFile(getConfig_VolumeIcon(params),
-                    volumeIconFile);
-
-            // background image
-            File bgdir = new File(mountedRoot, ".background");
-            bgdir.mkdirs();
-            IOUtils.copyFile(getConfig_VolumeBackground(params),
-                    new File(bgdir, "background.png"));
-
-            // Indicate that we want a custom icon
-            // NB: attributes of the root directory are ignored
-            // when creating the volume
-            // Therefore we have to do this after we mount image
-            String setFileUtility = findSetFileUtility();
-            if (setFileUtility != null) {
-                //can not find utility => keep going without icon
-                try {
-                    volumeIconFile.setWritable(true);
-                    // The "creator" attribute on a file is a legacy attribute
-                    // but it seems Finder excepts these bytes to be
-                    // "icnC" for the volume icon
-                    // (might not work on Mac 10.13 with old XCode)
-                    pb = new ProcessBuilder(
-                            setFileUtility,
-                            "-c", "icnC",
-                            volumeIconFile.getAbsolutePath());
-                    IOUtils.exec(pb);
-                    volumeIconFile.setReadOnly();
-
-                    pb = new ProcessBuilder(
-                            setFileUtility,
-                            "-a", "C",
-                            mountedRoot.getAbsolutePath());
-                    IOUtils.exec(pb);
-                } catch (IOException ex) {
-                    Log.error(ex.getMessage());
-                    Log.verbose("Cannot enable custom icon using SetFile utility");
-                }
-            } else {
-                Log.verbose(I18N.getString("message.setfile.dmg"));
-            }
-
-            // We will not consider setting background image and creating link to
-            // /Application folder in DMG as critical error, since it can fail in
-            // headless enviroment.
-            try {
-                pb = new ProcessBuilder("osascript",
-                        getConfig_VolumeScript(params).getAbsolutePath());
-                IOUtils.exec(pb);
-            } catch (IOException ex) {
-                Log.verbose(ex);
-            }
-        } finally {
-            // Detach the temporary image
-            pb = new ProcessBuilder(
-                    hdiutil,
-                    "detach",
-                    "-force",
-                    hdiUtilVerbosityFlag,
-                    mountedRoot.getAbsolutePath());
-            IOUtils.exec(pb);
-        }
-
-        // Compress it to a new image
-        pb = new ProcessBuilder(
-                hdiutil,
-                "convert",
-                protoDMG.getAbsolutePath(),
-                hdiUtilVerbosityFlag,
-                "-format", "UDZO",
-                "-o", finalDMG.getAbsolutePath());
-        IOUtils.exec(pb);
-
-        //add license if needed
-        if (getConfig_LicenseFile(params).exists()) {
-            //hdiutil unflatten your_image_file.dmg
-            pb = new ProcessBuilder(
-                    hdiutil,
-                    "unflatten",
-                    finalDMG.getAbsolutePath()
-            );
-            IOUtils.exec(pb);
-
-            //add license
-            pb = new ProcessBuilder(
-                    hdiutil,
-                    "udifrez",
-                    finalDMG.getAbsolutePath(),
-                    "-xml",
-                    getConfig_LicenseFile(params).getAbsolutePath()
-            );
-            IOUtils.exec(pb);
-
-            //hdiutil flatten your_image_file.dmg
-            pb = new ProcessBuilder(
-                    hdiutil,
-                    "flatten",
-                    finalDMG.getAbsolutePath()
-            );
-            IOUtils.exec(pb);
-
-        }
-
-        //Delete the temporary image
-        protoDMG.delete();
-
-        Log.verbose(MessageFormat.format(I18N.getString(
-                "message.output-to-location"),
-                APP_NAME.fetchFrom(params), finalDMG.getAbsolutePath()));
-
-        return finalDMG;
-    }
-
-
-    //////////////////////////////////////////////////////////////////////////
-    // Implement Bundler
-    //////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public String getName() {
-        return I18N.getString("dmg.bundler.name");
-    }
-
-    @Override
-    public String getID() {
-        return "dmg";
-    }
-
-    @Override
-    public boolean validate(Map<String, ? super Object> params)
-            throws ConfigException {
-        try {
-            Objects.requireNonNull(params);
-
-            //run basic validation to ensure requirements are met
-            //we are not interested in return code, only possible exception
-            validateAppImageAndBundeler(params);
-
-            return true;
-        } catch (RuntimeException re) {
-            if (re.getCause() instanceof ConfigException) {
-                throw (ConfigException) re.getCause();
-            } else {
-                throw new ConfigException(re);
-            }
-        }
-    }
-
-    @Override
-    public File execute(Map<String, ? super Object> params,
-            File outputParentDir) throws PackagerException {
-        return bundle(params, outputParentDir);
-    }
-
-    @Override
-    public boolean supported(boolean runtimeInstaller) {
-        return isSupported();
-    }
-
-    public final static String[] required =
-            {"/usr/bin/hdiutil", "/usr/bin/osascript"};
-    public static boolean isSupported() {
-        try {
-            for (String s : required) {
-                File f = new File(s);
-                if (!f.exists() || !f.canExecute()) {
-                    return false;
-                }
-            }
-            return true;
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    @Override
-    public boolean isDefault() {
-        return true;
-    }
-
-}
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,555 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.*;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.text.MessageFormat;
-import java.util.*;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
-import static jdk.jpackage.internal.MacBaseInstallerBundler.SIGNING_KEY_USER;
-import static jdk.jpackage.internal.MacAppImageBuilder.MAC_CF_BUNDLE_IDENTIFIER;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-
-public class MacPkgBundler extends MacBaseInstallerBundler {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MacResources");
-
-    private static final String DEFAULT_BACKGROUND_IMAGE = "background_pkg.png";
-
-    private static final String TEMPLATE_PREINSTALL_SCRIPT =
-            "preinstall.template";
-    private static final String TEMPLATE_POSTINSTALL_SCRIPT =
-            "postinstall.template";
-
-    private static final BundlerParamInfo<File> PACKAGES_ROOT =
-            new StandardBundlerParam<>(
-            "mac.pkg.packagesRoot",
-            File.class,
-            params -> {
-                File packagesRoot =
-                        new File(TEMP_ROOT.fetchFrom(params), "packages");
-                packagesRoot.mkdirs();
-                return packagesRoot;
-            },
-            (s, p) -> new File(s));
-
-
-    protected final BundlerParamInfo<File> SCRIPTS_DIR =
-            new StandardBundlerParam<>(
-            "mac.pkg.scriptsDir",
-            File.class,
-            params -> {
-                File scriptsDir =
-                        new File(CONFIG_ROOT.fetchFrom(params), "scripts");
-                scriptsDir.mkdirs();
-                return scriptsDir;
-            },
-            (s, p) -> new File(s));
-
-    public static final
-            BundlerParamInfo<String> DEVELOPER_ID_INSTALLER_SIGNING_KEY =
-            new StandardBundlerParam<>(
-            "mac.signing-key-developer-id-installer",
-            String.class,
-            params -> {
-                    String result = MacBaseInstallerBundler.findKey(
-                            "Developer ID Installer: "
-                            + SIGNING_KEY_USER.fetchFrom(params),
-                            SIGNING_KEYCHAIN.fetchFrom(params),
-                            VERBOSE.fetchFrom(params));
-                    if (result != null) {
-                        MacCertificate certificate = new MacCertificate(result);
-
-                        if (!certificate.isValid()) {
-                            Log.error(MessageFormat.format(
-                                    I18N.getString("error.certificate.expired"),
-                                    result));
-                        }
-                    }
-
-                    return result;
-                },
-            (s, p) -> s);
-
-    public static final BundlerParamInfo<String> MAC_INSTALL_DIR =
-            new StandardBundlerParam<>(
-            "mac-install-dir",
-            String.class,
-             params -> {
-                 String dir = INSTALL_DIR.fetchFrom(params);
-                 return (dir != null) ? dir : "/Applications";
-             },
-            (s, p) -> s
-    );
-
-    public static final BundlerParamInfo<String> INSTALLER_SUFFIX =
-            new StandardBundlerParam<> (
-            "mac.pkg.installerName.suffix",
-            String.class,
-            params -> "",
-            (s, p) -> s);
-
-    public File bundle(Map<String, ? super Object> params,
-            File outdir) throws PackagerException {
-        Log.verbose(MessageFormat.format(I18N.getString("message.building-pkg"),
-                APP_NAME.fetchFrom(params)));
-
-        IOUtils.writableOutputDir(outdir.toPath());
-
-        try {
-            File appImageDir = prepareAppBundle(params);
-
-            if (appImageDir != null && prepareConfigFiles(params)) {
-
-                File configScript = getConfig_Script(params);
-                if (configScript.exists()) {
-                    Log.verbose(MessageFormat.format(I18N.getString(
-                            "message.running-script"),
-                            configScript.getAbsolutePath()));
-                    IOUtils.run("bash", configScript);
-                }
-
-                return createPKG(params, outdir, appImageDir);
-            }
-            return null;
-        } catch (IOException ex) {
-            Log.verbose(ex);
-            throw new PackagerException(ex);
-        }
-    }
-
-    private File getPackages_AppPackage(Map<String, ? super Object> params) {
-        return new File(PACKAGES_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + "-app.pkg");
-    }
-
-    private File getConfig_DistributionXMLFile(
-            Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params), "distribution.dist");
-    }
-
-    private File getConfig_BackgroundImage(Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + "-background.png");
-    }
-
-    private File getConfig_BackgroundImageDarkAqua(Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + "-background-darkAqua.png");
-    }
-
-    private File getScripts_PreinstallFile(Map<String, ? super Object> params) {
-        return new File(SCRIPTS_DIR.fetchFrom(params), "preinstall");
-    }
-
-    private File getScripts_PostinstallFile(
-            Map<String, ? super Object> params) {
-        return new File(SCRIPTS_DIR.fetchFrom(params), "postinstall");
-    }
-
-    private String getAppIdentifier(Map<String, ? super Object> params) {
-        return MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params);
-    }
-
-    private void preparePackageScripts(Map<String, ? super Object> params)
-            throws IOException {
-        Log.verbose(I18N.getString("message.preparing-scripts"));
-
-        Map<String, String> data = new HashMap<>();
-
-        Path appLocation = Path.of(MAC_INSTALL_DIR.fetchFrom(params),
-                         APP_NAME.fetchFrom(params) + ".app", "Contents", "app");
-
-        data.put("INSTALL_LOCATION", MAC_INSTALL_DIR.fetchFrom(params));
-        data.put("APP_LOCATION", appLocation.toString());
-
-        createResource(TEMPLATE_PREINSTALL_SCRIPT, params)
-                .setCategory(I18N.getString("resource.pkg-preinstall-script"))
-                .setSubstitutionData(data)
-                .saveToFile(getScripts_PreinstallFile(params));
-        getScripts_PreinstallFile(params).setExecutable(true, false);
-
-        createResource(TEMPLATE_POSTINSTALL_SCRIPT, params)
-                .setCategory(I18N.getString("resource.pkg-postinstall-script"))
-                .setSubstitutionData(data)
-                .saveToFile(getScripts_PostinstallFile(params));
-        getScripts_PostinstallFile(params).setExecutable(true, false);
-    }
-
-    private static String URLEncoding(String pkgName) throws URISyntaxException {
-        URI uri = new URI(null, null, pkgName, null);
-        return uri.toASCIIString();
-    }
-
-    private void prepareDistributionXMLFile(Map<String, ? super Object> params)
-            throws IOException {
-        File f = getConfig_DistributionXMLFile(params);
-
-        Log.verbose(MessageFormat.format(I18N.getString(
-                "message.preparing-distribution-dist"), f.getAbsolutePath()));
-
-        IOUtils.createXml(f.toPath(), xml -> {
-            xml.writeStartElement("installer-gui-script");
-            xml.writeAttribute("minSpecVersion", "1");
-
-            xml.writeStartElement("title");
-            xml.writeCharacters(APP_NAME.fetchFrom(params));
-            xml.writeEndElement();
-
-            xml.writeStartElement("background");
-            xml.writeAttribute("file", getConfig_BackgroundImage(params).getName());
-            xml.writeAttribute("mime-type", "image/png");
-            xml.writeAttribute("alignment", "bottomleft");
-            xml.writeAttribute("scaling", "none");
-            xml.writeEndElement();
-
-            xml.writeStartElement("background-darkAqua");
-            xml.writeAttribute("file", getConfig_BackgroundImageDarkAqua(params).getName());
-            xml.writeAttribute("mime-type", "image/png");
-            xml.writeAttribute("alignment", "bottomleft");
-            xml.writeAttribute("scaling", "none");
-            xml.writeEndElement();
-
-            String licFileStr = LICENSE_FILE.fetchFrom(params);
-            if (licFileStr != null) {
-                File licFile = new File(licFileStr);
-                xml.writeStartElement("license");
-                xml.writeAttribute("file", licFile.getAbsolutePath());
-                xml.writeAttribute("mime-type", "text/rtf");
-                xml.writeEndElement();
-            }
-
-            /*
-             * Note that the content of the distribution file
-             * below is generated by productbuild --synthesize
-             */
-            String appId = getAppIdentifier(params);
-
-            xml.writeStartElement("pkg-ref");
-            xml.writeAttribute("id", appId);
-            xml.writeEndElement(); // </pkg-ref>
-            xml.writeStartElement("options");
-            xml.writeAttribute("customize", "never");
-            xml.writeAttribute("require-scripts", "false");
-            xml.writeEndElement(); // </options>
-            xml.writeStartElement("choices-outline");
-            xml.writeStartElement("line");
-            xml.writeAttribute("choice", "default");
-            xml.writeStartElement("line");
-            xml.writeAttribute("choice", appId);
-            xml.writeEndElement(); // </line>
-            xml.writeEndElement(); // </line>
-            xml.writeEndElement(); // </choices-outline>
-            xml.writeStartElement("choice");
-            xml.writeAttribute("id", "default");
-            xml.writeEndElement(); // </choice>
-            xml.writeStartElement("choice");
-            xml.writeAttribute("id", appId);
-            xml.writeAttribute("visible", "false");
-            xml.writeStartElement("pkg-ref");
-            xml.writeAttribute("id", appId);
-            xml.writeEndElement(); // </pkg-ref>
-            xml.writeEndElement(); // </choice>
-            xml.writeStartElement("pkg-ref");
-            xml.writeAttribute("id", appId);
-            xml.writeAttribute("version", VERSION.fetchFrom(params));
-            xml.writeAttribute("onConclusion", "none");
-            try {
-                xml.writeCharacters(URLEncoding(
-                        getPackages_AppPackage(params).getName()));
-            } catch (URISyntaxException ex) {
-                throw new IOException(ex);
-            }
-            xml.writeEndElement(); // </pkg-ref>
-
-            xml.writeEndElement(); // </installer-gui-script>
-        });
-    }
-
-    private boolean prepareConfigFiles(Map<String, ? super Object> params)
-            throws IOException {
-
-        createResource(DEFAULT_BACKGROUND_IMAGE, params)
-                .setCategory(I18N.getString("resource.pkg-background-image"))
-                .saveToFile(getConfig_BackgroundImage(params));
-
-        createResource(DEFAULT_BACKGROUND_IMAGE, params)
-                .setCategory(I18N.getString("resource.pkg-background-image"))
-                .saveToFile(getConfig_BackgroundImageDarkAqua(params));
-
-        prepareDistributionXMLFile(params);
-
-        createResource(null, params)
-                .setCategory(I18N.getString("resource.post-install-script"))
-                .saveToFile(getConfig_Script(params));
-
-        return true;
-    }
-
-    // name of post-image script
-    private File getConfig_Script(Map<String, ? super Object> params) {
-        return new File(CONFIG_ROOT.fetchFrom(params),
-                APP_NAME.fetchFrom(params) + "-post-image.sh");
-    }
-
-    private void patchCPLFile(File cpl) throws IOException {
-        String cplData = Files.readString(cpl.toPath());
-        String[] lines = cplData.split("\n");
-        try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(
-                cpl.toPath()))) {
-            int skip = 0;
-            // Used to skip Java.runtime bundle, since
-            // pkgbuild with --root will find two bundles app and Java runtime.
-            // We cannot generate component proprty list when using
-            // --component argument.
-            for (int i = 0; i < lines.length; i++) {
-                if (lines[i].trim().equals("<key>BundleIsRelocatable</key>")) {
-                    out.println(lines[i]);
-                    out.println("<false/>");
-                    i++;
-                } else if (lines[i].trim().equals("<key>ChildBundles</key>")) {
-                    ++skip;
-                } else if ((skip > 0) && lines[i].trim().equals("</array>")) {
-                    --skip;
-                } else {
-                    if (skip == 0) {
-                        out.println(lines[i]);
-                    }
-                }
-            }
-        }
-    }
-
-    // pkgbuild includes all components from "--root" and subfolders,
-    // so if we have app image in folder which contains other images, then they
-    // will be included as well. It does have "--filter" option which use regex
-    // to exclude files/folder, but it will overwrite default one which excludes
-    // based on doc "any .svn or CVS directories, and any .DS_Store files".
-    // So easy aproach will be to copy user provided app-image into temp folder
-    // if root path contains other files.
-    private String getRoot(Map<String, ? super Object> params,
-            File appLocation) throws IOException {
-        String root = appLocation.getParent() == null ?
-                "." : appLocation.getParent();
-        File rootDir = new File(root);
-        File[] list = rootDir.listFiles();
-        if (list != null) { // Should not happend
-            // We should only have app image and/or .DS_Store
-            if (list.length == 1) {
-                return root;
-            } else if (list.length == 2) {
-                // Check case with app image and .DS_Store
-                if (list[0].toString().toLowerCase().endsWith(".ds_store") ||
-                    list[1].toString().toLowerCase().endsWith(".ds_store")) {
-                    return root; // Only app image and .DS_Store
-                }
-            }
-        }
-
-        // Copy to new root
-        Path newRoot = Files.createTempDirectory(
-                TEMP_ROOT.fetchFrom(params).toPath(),
-                "root-");
-
-        IOUtils.copyRecursive(appLocation.toPath(),
-                newRoot.resolve(appLocation.getName()));
-
-        return newRoot.toString();
-    }
-
-    private File createPKG(Map<String, ? super Object> params,
-            File outdir, File appLocation) {
-        // generic find attempt
-        try {
-            File appPKG = getPackages_AppPackage(params);
-
-            String root = getRoot(params, appLocation);
-
-            // Generate default CPL file
-            File cpl = new File(CONFIG_ROOT.fetchFrom(params).getAbsolutePath()
-                    + File.separator + "cpl.plist");
-            ProcessBuilder pb = new ProcessBuilder("pkgbuild",
-                    "--root",
-                    root,
-                    "--install-location",
-                    MAC_INSTALL_DIR.fetchFrom(params),
-                    "--analyze",
-                    cpl.getAbsolutePath());
-
-            IOUtils.exec(pb);
-
-            patchCPLFile(cpl);
-
-            preparePackageScripts(params);
-
-            // build application package
-            pb = new ProcessBuilder("pkgbuild",
-                    "--root",
-                    root,
-                    "--install-location",
-                    MAC_INSTALL_DIR.fetchFrom(params),
-                    "--component-plist",
-                    cpl.getAbsolutePath(),
-                    "--scripts",
-                    SCRIPTS_DIR.fetchFrom(params).getAbsolutePath(),
-                    appPKG.getAbsolutePath());
-            IOUtils.exec(pb);
-
-            // build final package
-            File finalPKG = new File(outdir, INSTALLER_NAME.fetchFrom(params)
-                    + INSTALLER_SUFFIX.fetchFrom(params)
-                    + ".pkg");
-            outdir.mkdirs();
-
-            List<String> commandLine = new ArrayList<>();
-            commandLine.add("productbuild");
-
-            commandLine.add("--resources");
-            commandLine.add(CONFIG_ROOT.fetchFrom(params).getAbsolutePath());
-
-            // maybe sign
-            if (Optional.ofNullable(MacAppImageBuilder.
-                    SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) {
-                if (Platform.getMajorVersion() > 10 ||
-                    (Platform.getMajorVersion() == 10 &&
-                    Platform.getMinorVersion() >= 12)) {
-                    // we need this for OS X 10.12+
-                    Log.verbose(I18N.getString("message.signing.pkg"));
-                }
-
-                String signingIdentity =
-                        DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
-                if (signingIdentity != null) {
-                    commandLine.add("--sign");
-                    commandLine.add(signingIdentity);
-                }
-
-                String keychainName = SIGNING_KEYCHAIN.fetchFrom(params);
-                if (keychainName != null && !keychainName.isEmpty()) {
-                    commandLine.add("--keychain");
-                    commandLine.add(keychainName);
-                }
-            }
-
-            commandLine.add("--distribution");
-            commandLine.add(
-                    getConfig_DistributionXMLFile(params).getAbsolutePath());
-            commandLine.add("--package-path");
-            commandLine.add(PACKAGES_ROOT.fetchFrom(params).getAbsolutePath());
-
-            commandLine.add(finalPKG.getAbsolutePath());
-
-            pb = new ProcessBuilder(commandLine);
-            IOUtils.exec(pb);
-
-            return finalPKG;
-        } catch (Exception ignored) {
-            Log.verbose(ignored);
-            return null;
-        }
-    }
-
-    //////////////////////////////////////////////////////////////////////////
-    // Implement Bundler
-    //////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public String getName() {
-        return I18N.getString("pkg.bundler.name");
-    }
-
-    @Override
-    public String getID() {
-        return "pkg";
-    }
-
-    @Override
-    public boolean validate(Map<String, ? super Object> params)
-            throws ConfigException {
-        try {
-            Objects.requireNonNull(params);
-
-            // run basic validation to ensure requirements are met
-            // we are not interested in return code, only possible exception
-            validateAppImageAndBundeler(params);
-
-            if (MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) == null) {
-                throw new ConfigException(
-                        I18N.getString("message.app-image-requires-identifier"),
-                        I18N.getString(
-                            "message.app-image-requires-identifier.advice"));
-            }
-
-            // reject explicitly set sign to true and no valid signature key
-            if (Optional.ofNullable(MacAppImageBuilder.
-                    SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) {
-                String signingIdentity =
-                        DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params);
-                if (signingIdentity == null) {
-                    throw new ConfigException(
-                            I18N.getString("error.explicit-sign-no-cert"),
-                            I18N.getString(
-                            "error.explicit-sign-no-cert.advice"));
-                }
-            }
-
-            // hdiutil is always available so there's no need
-            // to test for availability.
-
-            return true;
-        } catch (RuntimeException re) {
-            if (re.getCause() instanceof ConfigException) {
-                throw (ConfigException) re.getCause();
-            } else {
-                throw new ConfigException(re);
-            }
-        }
-    }
-
-    @Override
-    public File execute(Map<String, ? super Object> params,
-            File outputParentDir) throws PackagerException {
-        return bundle(params, outputParentDir);
-    }
-
-    @Override
-    public boolean supported(boolean runtimeInstaller) {
-        return true;
-    }
-
-    @Override
-    public boolean isDefault() {
-        return false;
-    }
-
-}
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/DMGsetup.scpt	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-tell application "Finder"
-  tell disk "DEPLOY_ACTUAL_VOLUME_NAME"
-    open
-    set current view of container window to icon view
-    set toolbar visible of container window to false
-    set statusbar visible of container window to false
-
-    -- size of window should match size of background
-    set the bounds of container window to {400, 100, 917, 380}
-
-    set theViewOptions to the icon view options of container window
-    set arrangement of theViewOptions to not arranged
-    set icon size of theViewOptions to 128
-    set background picture of theViewOptions to file ".background:background.png"
-
-    -- Create alias for install location
-    make new alias file at container window to DEPLOY_INSTALL_LOCATION with properties {name:"DEPLOY_INSTALL_NAME"}
-
-    set allTheFiles to the name of every item of container window
-    repeat with theFile in allTheFiles
-      set theFilePath to POSIX Path of theFile
-      if theFilePath is "/DEPLOY_APPLICATION_NAME.app"
-        -- Position application location
-        set position of item theFile of container window to {120, 130}
-      else if theFilePath is "/DEPLOY_INSTALL_NAME"
-        -- Position install location
-        set position of item theFile of container window to {390, 130}
-      else
-        -- Move all other files far enough to be not visible if user has "show hidden files" option set
-        set position of item theFile of container window to {1000, 130}
-      end
-    end repeat
-
-    update without registering applications
-    delay 5
-    close
-  end tell
-end tell
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/Info-lite.plist.template	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-<?xml version="1.0" ?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
- <dict>
-  <key>LSMinimumSystemVersion</key>
-  <string>10.9</string>
-  <key>CFBundleDevelopmentRegion</key>
-  <string>English</string>
-  <key>CFBundleAllowMixedLocalizations</key>
-  <true/>
-  <key>CFBundleExecutable</key>
-  <string>DEPLOY_LAUNCHER_NAME</string>
-  <key>CFBundleIconFile</key>
-  <string>DEPLOY_ICON_FILE</string>
-  <key>CFBundleIdentifier</key>
-  <string>DEPLOY_BUNDLE_IDENTIFIER</string>
-  <key>CFBundleInfoDictionaryVersion</key>
-  <string>6.0</string>
-  <key>CFBundleName</key>
-  <string>DEPLOY_BUNDLE_NAME</string>
-  <key>CFBundlePackageType</key>
-  <string>APPL</string>
-  <key>CFBundleShortVersionString</key>
-  <string>DEPLOY_BUNDLE_SHORT_VERSION</string>
-  <key>CFBundleSignature</key>
-  <string>????</string>
-  <!-- See https://developer.apple.com/app-store/categories/ for list of AppStore categories -->
-  <key>LSApplicationCategoryType</key>
-  <string>Unknown</string>
-  <key>CFBundleVersion</key>
-  <string>DEPLOY_BUNDLE_CFBUNDLE_VERSION</string>
-  <key>NSHumanReadableCopyright</key>
-  <string>DEPLOY_BUNDLE_COPYRIGHT</string>DEPLOY_FILE_ASSOCIATIONS
-  <key>NSHighResolutionCapable</key>
-  <string>true</string>
- </dict>
-</plist>
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacAppStore.entitlements	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-    <dict>
-        <key>com.apple.security.app-sandbox</key>
-        <true/>
-    </dict>
-</plist>
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacAppStore_Inherit.entitlements	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-    <dict>
-        <key>com.apple.security.app-sandbox</key>
-        <true/>
-        <key>com.apple.security.inherit</key>
-        <true/>
-    </dict>
-</plist>
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-app.bundler.name=Mac Application Image
-store.bundler.name=Mac App Store Ready Bundler
-dmg.bundler.name=Mac DMG Package
-pkg.bundler.name=Mac PKG Package
-
-error.invalid-cfbundle-version=Invalid CFBundleVersion: [{0}]
-error.invalid-cfbundle-version.advice=Set a compatible 'appVersion' or set a 'mac.CFBundleVersion'. Valid versions are one to three integers separated by dots.
-error.explicit-sign-no-cert=Signature explicitly requested but no signing certificate specified
-error.explicit-sign-no-cert.advice=Either specify a valid cert in 'mac.signing-key-developer-id-app' or unset 'signBundle' or set 'signBundle' to false.
-error.must-sign-app-store=Mac App Store apps must be signed, and signing has been disabled by bundler configuration
-error.must-sign-app-store.advice=Either unset 'signBundle' or set 'signBundle' to true
-error.no-app-signing-key=No Mac App Store App Signing Key
-error.no-app-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
-error.no-pkg-signing-key=No Mac App Store Installer Signing Key
-error.no-pkg-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
-error.certificate.expired=Error: Certificate expired {0}
-error.no.xcode.signing=Xcode with command line developer tools is required for signing
-error.no.xcode.signing.advice=Install Xcode with command line developer tools.
-
-resource.bundle-config-file=Bundle config file
-resource.app-info-plist=Application Info.plist
-resource.runtime-info-plist=Java Runtime Info.plist
-resource.mac-app-store-entitlements=Mac App Store Entitlements
-resource.mac-app-store-inherit-entitlements=Mac App Store Inherit Entitlements
-resource.dmg-setup-script=DMG setup script
-resource.license-setup=License setup
-resource.dmg-background=dmg background
-resource.volume-icon=volume icon
-resource.post-install-script=script to run after application image is populated
-resource.pkg-preinstall-script=PKG preinstall script
-resource.pkg-postinstall-script=PKG postinstall script
-resource.pkg-background-image=pkg background image
-
-
-message.bundle-name-too-long-warning={0} is set to ''{1}'', which is longer than 16 characters. For a better Mac experience consider shortening it.
-message.null-classpath=Null app resources?
-message.preparing-info-plist=Preparing Info.plist: {0}.
-message.icon-not-icns= The specified icon "{0}" is not an ICNS file and will not be used. The default icon will be used in it's place.
-message.version-string-too-many-components=Version sting may have between 1 and 3 numbers: 1, 1.2, 1.2.3.
-message.version-string-first-number-not-zero=The first number in a CFBundleVersion cannot be zero or negative.
-message.version-string-no-negative-numbers=Negative numbers are not allowed in version strings.
-message.version-string-numbers-only=Version strings can consist of only numbers and up to two dots.
-message.creating-association-with-null-extension=Creating association with null extension.
-message.ignoring.symlink=Warning: codesign is skipping the symlink {0}.
-message.keychain.error=Error: unable to get keychain list.
-message.building-bundle=Building Mac App Store Package for {0}.
-message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists.
-message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists.
-message.app-image-requires-app-name=When using an external app image you must specify the app name.
-message.app-image-requires-app-name.advice=Set the app name via the -name CLI flag, the fx:application/@name ANT attribute, or via the 'appName' bundler argument.
-message.app-image-requires-identifier=Unable to extract identifier from app image.
-message.app-image-requires-identifier.advice=Use "--verbose" for extended error message or specify it via "--mac-package-identifier".
-message.building-dmg=Building DMG package for {0}.
-message.running-script=Running shell script on application image [{0}].
-message.preparing-dmg-setup=Preparing dmg setup: {0}.
-message.creating-dmg-file=Creating DMG file: {0}.
-message.dmg-cannot-be-overwritten=Dmg file exists ({0} and can not be removed.
-message.output-to-location=Result DMG installer for {0}: {1}.
-message.building-pkg=Building PKG package for {0}.
-message.preparing-scripts=Preparing package scripts.
-message.preparing-distribution-dist=Preparing distribution.dist: {0}.
-message.signing.pkg=Warning: For signing PKG, you might need to set "Always Trust" for your certificate using "Keychain Access" tool.
-message.setfile.dmg=Setting custom icon on DMG file skipped because 'SetFile' utility was not found. Installing Xcode with Command Line Tools should resolve this issue.
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-app.bundler.name=Mac Application Image
-store.bundler.name=Mac App Store Ready Bundler
-dmg.bundler.name=Mac DMG Package
-pkg.bundler.name=Mac PKG Package
-
-error.invalid-cfbundle-version=Invalid CFBundleVersion: [{0}]
-error.invalid-cfbundle-version.advice=Set a compatible 'appVersion' or set a 'mac.CFBundleVersion'. Valid versions are one to three integers separated by dots.
-error.explicit-sign-no-cert=Signature explicitly requested but no signing certificate specified
-error.explicit-sign-no-cert.advice=Either specify a valid cert in 'mac.signing-key-developer-id-app' or unset 'signBundle' or set 'signBundle' to false.
-error.must-sign-app-store=Mac App Store apps must be signed, and signing has been disabled by bundler configuration
-error.must-sign-app-store.advice=Either unset 'signBundle' or set 'signBundle' to true
-error.no-app-signing-key=No Mac App Store App Signing Key
-error.no-app-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
-error.no-pkg-signing-key=No Mac App Store Installer Signing Key
-error.no-pkg-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
-error.certificate.expired=Error: Certificate expired {0}
-error.no.xcode.signing=Xcode with command line developer tools is required for signing
-error.no.xcode.signing.advice=Install Xcode with command line developer tools.
-
-resource.bundle-config-file=Bundle config file
-resource.app-info-plist=Application Info.plist
-resource.runtime-info-plist=Java Runtime Info.plist
-resource.mac-app-store-entitlements=Mac App Store Entitlements
-resource.mac-app-store-inherit-entitlements=Mac App Store Inherit Entitlements
-resource.dmg-setup-script=DMG setup script
-resource.license-setup=License setup
-resource.dmg-background=dmg background
-resource.volume-icon=volume icon
-resource.post-install-script=script to run after application image is populated
-resource.pkg-preinstall-script=PKG preinstall script
-resource.pkg-postinstall-script=PKG postinstall script
-resource.pkg-background-image=pkg background image
-
-
-message.bundle-name-too-long-warning={0} is set to ''{1}'', which is longer than 16 characters. For a better Mac experience consider shortening it.
-message.null-classpath=Null app resources?
-message.preparing-info-plist=Preparing Info.plist: {0}.
-message.icon-not-icns= The specified icon "{0}" is not an ICNS file and will not be used. The default icon will be used in it's place.
-message.version-string-too-many-components=Version sting may have between 1 and 3 numbers: 1, 1.2, 1.2.3.
-message.version-string-first-number-not-zero=The first number in a CFBundleVersion cannot be zero or negative.
-message.version-string-no-negative-numbers=Negative numbers are not allowed in version strings.
-message.version-string-numbers-only=Version strings can consist of only numbers and up to two dots.
-message.creating-association-with-null-extension=Creating association with null extension.
-message.ignoring.symlink=Warning: codesign is skipping the symlink {0}.
-message.keychain.error=Error: unable to get keychain list.
-message.building-bundle=Building Mac App Store Package for {0}.
-message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists.
-message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists.
-message.app-image-requires-app-name=When using an external app image you must specify the app name.
-message.app-image-requires-app-name.advice=Set the app name via the -name CLI flag, the fx:application/@name ANT attribute, or via the 'appName' bundler argument.
-message.app-image-requires-identifier=Unable to extract identifier from app image.
-message.app-image-requires-identifier.advice=Use "--verbose" for extended error message or specify it via "--mac-package-identifier".
-message.building-dmg=Building DMG package for {0}.
-message.running-script=Running shell script on application image [{0}].
-message.preparing-dmg-setup=Preparing dmg setup: {0}.
-message.creating-dmg-file=Creating DMG file: {0}.
-message.dmg-cannot-be-overwritten=Dmg file exists ({0} and can not be removed.
-message.output-to-location=Result DMG installer for {0}: {1}.
-message.building-pkg=Building PKG package for {0}.
-message.preparing-scripts=Preparing package scripts.
-message.preparing-distribution-dist=Preparing distribution.dist: {0}.
-message.signing.pkg=Warning: For signing PKG, you might need to set "Always Trust" for your certificate using "Keychain Access" tool.
-message.setfile.dmg=Setting custom icon on DMG file skipped because 'SetFile' utility was not found. Installing Xcode with Command Line Tools should resolve this issue.
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-app.bundler.name=Mac Application Image
-store.bundler.name=Mac App Store Ready Bundler
-dmg.bundler.name=Mac DMG Package
-pkg.bundler.name=Mac PKG Package
-
-error.invalid-cfbundle-version=Invalid CFBundleVersion: [{0}]
-error.invalid-cfbundle-version.advice=Set a compatible 'appVersion' or set a 'mac.CFBundleVersion'. Valid versions are one to three integers separated by dots.
-error.explicit-sign-no-cert=Signature explicitly requested but no signing certificate specified
-error.explicit-sign-no-cert.advice=Either specify a valid cert in 'mac.signing-key-developer-id-app' or unset 'signBundle' or set 'signBundle' to false.
-error.must-sign-app-store=Mac App Store apps must be signed, and signing has been disabled by bundler configuration
-error.must-sign-app-store.advice=Either unset 'signBundle' or set 'signBundle' to true
-error.no-app-signing-key=No Mac App Store App Signing Key
-error.no-app-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
-error.no-pkg-signing-key=No Mac App Store Installer Signing Key
-error.no-pkg-signing-key.advice=Install your app signing keys into your Mac Keychain using XCode.
-error.certificate.expired=Error: Certificate expired {0}
-error.no.xcode.signing=Xcode with command line developer tools is required for signing
-error.no.xcode.signing.advice=Install Xcode with command line developer tools.
-
-resource.bundle-config-file=Bundle config file
-resource.app-info-plist=Application Info.plist
-resource.runtime-info-plist=Java Runtime Info.plist
-resource.mac-app-store-entitlements=Mac App Store Entitlements
-resource.mac-app-store-inherit-entitlements=Mac App Store Inherit Entitlements
-resource.dmg-setup-script=DMG setup script
-resource.license-setup=License setup
-resource.dmg-background=dmg background
-resource.volume-icon=volume icon
-resource.post-install-script=script to run after application image is populated
-resource.pkg-preinstall-script=PKG preinstall script
-resource.pkg-postinstall-script=PKG postinstall script
-resource.pkg-background-image=pkg background image
-
-
-message.bundle-name-too-long-warning={0} is set to ''{1}'', which is longer than 16 characters. For a better Mac experience consider shortening it.
-message.null-classpath=Null app resources?
-message.preparing-info-plist=Preparing Info.plist: {0}.
-message.icon-not-icns= The specified icon "{0}" is not an ICNS file and will not be used. The default icon will be used in it's place.
-message.version-string-too-many-components=Version sting may have between 1 and 3 numbers: 1, 1.2, 1.2.3.
-message.version-string-first-number-not-zero=The first number in a CFBundleVersion cannot be zero or negative.
-message.version-string-no-negative-numbers=Negative numbers are not allowed in version strings.
-message.version-string-numbers-only=Version strings can consist of only numbers and up to two dots.
-message.creating-association-with-null-extension=Creating association with null extension.
-message.ignoring.symlink=Warning: codesign is skipping the symlink {0}.
-message.keychain.error=Error: unable to get keychain list.
-message.building-bundle=Building Mac App Store Package for {0}.
-message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists.
-message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists.
-message.app-image-requires-app-name=When using an external app image you must specify the app name.
-message.app-image-requires-app-name.advice=Set the app name via the -name CLI flag, the fx:application/@name ANT attribute, or via the 'appName' bundler argument.
-message.app-image-requires-identifier=Unable to extract identifier from app image.
-message.app-image-requires-identifier.advice=Use "--verbose" for extended error message or specify it via "--mac-package-identifier".
-message.building-dmg=Building DMG package for {0}.
-message.running-script=Running shell script on application image [{0}].
-message.preparing-dmg-setup=Preparing dmg setup: {0}.
-message.creating-dmg-file=Creating DMG file: {0}.
-message.dmg-cannot-be-overwritten=Dmg file exists ({0} and can not be removed.
-message.output-to-location=Result DMG installer for {0}: {1}.
-message.building-pkg=Building PKG package for {0}.
-message.preparing-scripts=Preparing package scripts.
-message.preparing-distribution-dist=Preparing distribution.dist: {0}.
-message.signing.pkg=Warning: For signing PKG, you might need to set "Always Trust" for your certificate using "Keychain Access" tool.
-message.setfile.dmg=Setting custom icon on DMG file skipped because 'SetFile' utility was not found. Installing Xcode with Command Line Tools should resolve this issue.
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/Runtime-Info.plist.template	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-        <key>CFBundleDevelopmentRegion</key>
-        <string>English</string>
-        <key>CFBundleExecutable</key>
-        <string>libjli.dylib</string>
-        <key>CFBundleIdentifier</key>
-        <string>CF_BUNDLE_IDENTIFIER</string>
-        <key>CFBundleInfoDictionaryVersion</key>
-        <string>7.0</string>
-        <key>CFBundleName</key>
-        <string>CF_BUNDLE_NAME</string>
-        <key>CFBundlePackageType</key>
-        <string>BNDL</string>
-        <key>CFBundleShortVersionString</key>
-        <string>CF_BUNDLE_SHORT_VERSION_STRING</string>
-        <key>CFBundleSignature</key>
-        <string>????</string>
-        <key>CFBundleVersion</key>
-        <string>CF_BUNDLE_VERSION</string>
-</dict>
-</plist>
Binary file src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/background_dmg.png has changed
Binary file src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/background_pkg.png has changed
Binary file src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/java.icns has changed
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/lic_template.plist	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,244 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>LPic</key>
-	<array>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAAAAgAAAAAAAAAAAAQAAA==</data>
-			<key>ID</key>
-			<string>5000</string>
-			<key>Name</key>
-			<string></string>
-		</dict>
-	</array>
-	<key>STR#</key>
-	<array>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYPRW5nbGlzaCBkZWZhdWx0BUFncmVlCERpc2FncmVlBVByaW50B1NhdmUuLi56SWYgeW91IGFncmVlIHdpdGggdGhlIHRlcm1zIG9mIHRoaXMgbGljZW5zZSwgY2xpY2sgIkFncmVlIiB0byBhY2Nlc3MgdGhlIHNvZnR3YXJlLiAgSWYgeW91IGRvIG5vdCBhZ3JlZSwgcHJlc3MgIkRpc2FncmVlLiI=</data>
-			<key>ID</key>
-			<string>5000</string>
-			<key>Name</key>
-			<string>English buttons</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYHRGV1dHNjaAtBa3plcHRpZXJlbghBYmxlaG5lbgdEcnVja2VuClNpY2hlcm4uLi7nS2xpY2tlbiBTaWUgaW4g0kFremVwdGllcmVu0ywgd2VubiBTaWUgbWl0IGRlbiBCZXN0aW1tdW5nZW4gZGVzIFNvZnR3YXJlLUxpemVuenZlcnRyYWdzIGVpbnZlcnN0YW5kZW4gc2luZC4gRmFsbHMgbmljaHQsIGJpdHRlINJBYmxlaG5lbtMgYW5rbGlja2VuLiBTaWUga5pubmVuIGRpZSBTb2Z0d2FyZSBudXIgaW5zdGFsbGllcmVuLCB3ZW5uIFNpZSDSQWt6ZXB0aWVyZW7TIGFuZ2VrbGlja3QgaGFiZW4u</data>
-			<key>ID</key>
-			<string>5001</string>
-			<key>Name</key>
-			<string>German</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYHRW5nbGlzaAVBZ3JlZQhEaXNhZ3JlZQVQcmludAdTYXZlLi4ue0lmIHlvdSBhZ3JlZSB3aXRoIHRoZSB0ZXJtcyBvZiB0aGlzIGxpY2Vuc2UsIHByZXNzICJBZ3JlZSIgdG8gaW5zdGFsbCB0aGUgc29mdHdhcmUuICBJZiB5b3UgZG8gbm90IGFncmVlLCBwcmVzcyAiRGlzYWdyZWUiLg==</data>
-			<key>ID</key>
-			<string>5002</string>
-			<key>Name</key>
-			<string>English</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYHRXNwYZZvbAdBY2VwdGFyCk5vIGFjZXB0YXIISW1wcmltaXIKR3VhcmRhci4uLsBTaSBlc3SHIGRlIGFjdWVyZG8gY29uIGxvcyB0jnJtaW5vcyBkZSBlc3RhIGxpY2VuY2lhLCBwdWxzZSAiQWNlcHRhciIgcGFyYSBpbnN0YWxhciBlbCBzb2Z0d2FyZS4gRW4gZWwgc3VwdWVzdG8gZGUgcXVlIG5vIGVzdI4gZGUgYWN1ZXJkbyBjb24gbG9zIHSOcm1pbm9zIGRlIGVzdGEgbGljZW5jaWEsIHB1bHNlICJObyBhY2VwdGFyLiI=</data>
-			<key>ID</key>
-			<string>5003</string>
-			<key>Name</key>
-			<string>Spanish</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYIRnJhbo1haXMIQWNjZXB0ZXIHUmVmdXNlcghJbXByaW1lcg5FbnJlZ2lzdHJlci4uLrpTaSB2b3VzIGFjY2VwdGV6IGxlcyB0ZXJtZXMgZGUgbGEgcHKOc2VudGUgbGljZW5jZSwgY2xpcXVleiBzdXIgIkFjY2VwdGVyIiBhZmluIGQnaW5zdGFsbGVyIGxlIGxvZ2ljaWVsLiBTaSB2b3VzIG4nkHRlcyBwYXMgZCdhY2NvcmQgYXZlYyBsZXMgdGVybWVzIGRlIGxhIGxpY2VuY2UsIGNsaXF1ZXogc3VyICJSZWZ1c2VyIi4=</data>
-			<key>ID</key>
-			<string>5004</string>
-			<key>Name</key>
-			<string>French</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYISXRhbGlhbm8HQWNjZXR0bwdSaWZpdXRvBlN0YW1wYQtSZWdpc3RyYS4uLn9TZSBhY2NldHRpIGxlIGNvbmRpemlvbmkgZGkgcXVlc3RhIGxpY2VuemEsIGZhaSBjbGljIHN1ICJBY2NldHRvIiBwZXIgaW5zdGFsbGFyZSBpbCBzb2Z0d2FyZS4gQWx0cmltZW50aSBmYWkgY2xpYyBzdSAiUmlmaXV0byIu</data>
-			<key>ID</key>
-			<string>5005</string>
-			<key>Name</key>
-			<string>Italian</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYISmFwYW5lc2UKk6+I04K1gtyCtwyTr4jTgrWC3IK5gvEIiPON/IK3gukHlduRti4uLrSWe4Ncg3SDZ4NFg0eDQY5nl3CLlpH4jF+W8YLMj/CMj4LJk6+I04KzguqC6Y/qjYeCyYLNgUGDXIN0g2eDRYNHg0GC8INDg5ODWINngVuDi4K3gumCvYLfgsmBdZOviNOCtYLcgreBdoLwiZ+CtYLEgq2CvoKzgqKBQoFAk6+I04KzguqCyIKij+qNh4LJgs2BQYF1k6+I04K1gtyCuYLxgXaC8ImfgrWCxIKtgr6Cs4KigUI=</data>
-			<key>ID</key>
-			<string>5006</string>
-			<key>Name</key>
-			<string>Japanese</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYKTmVkZXJsYW5kcwJKYQNOZWUFUHJpbnQJQmV3YWFyLi4upEluZGllbiB1IGFra29vcmQgZ2FhdCBtZXQgZGUgdm9vcndhYXJkZW4gdmFuIGRlemUgbGljZW50aWUsIGt1bnQgdSBvcCAnSmEnIGtsaWtrZW4gb20gZGUgcHJvZ3JhbW1hdHV1ciB0ZSBpbnN0YWxsZXJlbi4gSW5kaWVuIHUgbmlldCBha2tvb3JkIGdhYXQsIGtsaWt0IHUgb3AgJ05lZScu</data>
-			<key>ID</key>
-			<string>5007</string>
-			<key>Name</key>
-			<string>Dutch</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYGU3ZlbnNrCEdvZGuKbm5zBkF2YppqcwhTa3JpdiB1dAhTcGFyYS4uLpNPbSBEdSBnb2Rrim5uZXIgbGljZW5zdmlsbGtvcmVuIGtsaWNrYSBwjCAiR29ka4pubnMiIGaaciBhdHQgaW5zdGFsbGVyYSBwcm9ncmFtcHJvZHVrdGVuLiBPbSBEdSBpbnRlIGdvZGuKbm5lciBsaWNlbnN2aWxsa29yZW4sIGtsaWNrYSBwjCAiQXZimmpzIi4=</data>
-			<key>ID</key>
-			<string>5008</string>
-			<key>Name</key>
-			<string>Swedish</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYRUG9ydHVndZBzLCBCcmFzaWwJQ29uY29yZGFyCURpc2NvcmRhcghJbXByaW1pcglTYWx2YXIuLi6MU2UgZXN0hyBkZSBhY29yZG8gY29tIG9zIHRlcm1vcyBkZXN0YSBsaWNlbo1hLCBwcmVzc2lvbmUgIkNvbmNvcmRhciIgcGFyYSBpbnN0YWxhciBvIHNvZnR3YXJlLiBTZSBui28gZXN0hyBkZSBhY29yZG8sIHByZXNzaW9uZSAiRGlzY29yZGFyIi4=</data>
-			<key>ID</key>
-			<string>5009</string>
-			<key>Name</key>
-			<string>Brazilian Portuguese</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYSU2ltcGxpZmllZCBDaGluZXNlBM2s0uIGsrvNrNLiBLTy06EGtOa0oqGtVMjnufvE+s2s0uKxvtDtv8nQrdLptcTM9b/uo6zH67C0obDNrNLiobHAtLCy17C0y8jtvP6ho8jnufvE+rK7zazS4qOsx+uwtKGwsrvNrNLiobGhow==</data>
-			<key>ID</key>
-			<string>5010</string>
-			<key>Name</key>
-			<string>Simplified Chinese</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYTVHJhZGl0aW9uYWwgQ2hpbmVzZQSmULdOBqSjplC3TgSmQ6ZMBsB4pnOhS1CmcKpHsXqmULdOpbuzXKVpw9K4zKq6sfi02qFBvdCr9qGnplC3TqGopUimd7jLs27F6aFDpnCqR6SjplC3TqFBvdCr9qGnpKOmULdOoaihQw==</data>
-			<key>ID</key>
-			<string>5011</string>
-			<key>Name</key>
-			<string>Traditional Chinese</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYFRGFuc2sERW5pZwVVZW5pZwdVZHNrcml2CkFya2l2ZXIuLi6YSHZpcyBkdSBhY2NlcHRlcmVyIGJldGluZ2Vsc2VybmUgaSBsaWNlbnNhZnRhbGVuLCBza2FsIGR1IGtsaWtrZSBwjCDSRW5pZ9MgZm9yIGF0IGluc3RhbGxlcmUgc29mdHdhcmVuLiBLbGlrIHCMINJVZW5pZ9MgZm9yIGF0IGFubnVsbGVyZSBpbnN0YWxsZXJpbmdlbi4=</data>
-			<key>ID</key>
-			<string>5012</string>
-			<key>Name</key>
-			<string>Danish</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYFU3VvbWkISHl2imtzeW4KRW4gaHl2imtzeQdUdWxvc3RhCVRhbGxlbm5hyW9IeXaKa3N5IGxpc2Vuc3Npc29waW11a3NlbiBlaGRvdCBvc29pdHRhbWFsbGEg1Uh5doprc3nVLiBKb3MgZXQgaHl2imtzeSBzb3BpbXVrc2VuIGVodG9qYSwgb3NvaXRhINVFbiBoeXaKa3N51S4=</data>
-			<key>ID</key>
-			<string>5013</string>
-			<key>Name</key>
-			<string>Finnish</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYRRnJhbo1haXMgY2FuYWRpZW4IQWNjZXB0ZXIHUmVmdXNlcghJbXByaW1lcg5FbnJlZ2lzdHJlci4uLrpTaSB2b3VzIGFjY2VwdGV6IGxlcyB0ZXJtZXMgZGUgbGEgcHKOc2VudGUgbGljZW5jZSwgY2xpcXVleiBzdXIgIkFjY2VwdGVyIiBhZmluIGQnaW5zdGFsbGVyIGxlIGxvZ2ljaWVsLiBTaSB2b3VzIG4nkHRlcyBwYXMgZCdhY2NvcmQgYXZlYyBsZXMgdGVybWVzIGRlIGxhIGxpY2VuY2UsIGNsaXF1ZXogc3VyICJSZWZ1c2VyIi4=</data>
-			<key>ID</key>
-			<string>5014</string>
-			<key>Name</key>
-			<string>French Canadian</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYGS29yZWFuBLW/wMcJtb/AxyC+yMfUBsfBuLDGrgfA+sDlLi4ufrvnv+sgsOi+4LytwMcgs7u/67+hILW/wMfHz7jpLCAitb/AxyIgtNzD37imILStt68gvNLHwcauv/6+7rimILyzxKHHz73KvcO/wC4gtb/Ax8fPwfYgvsq0wrTZuOksICK1v8DHIL7Ix9QiILTcw9+4piC0qbijvcq9w7/ALg==</data>
-			<key>ID</key>
-			<string>5015</string>
-			<key>Name</key>
-			<string>Korean</string>
-		</dict>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAYFTm9yc2sERW5pZwlJa2tlIGVuaWcIU2tyaXYgdXQKQXJraXZlci4uLqNIdmlzIERlIGVyIGVuaWcgaSBiZXN0ZW1tZWxzZW5lIGkgZGVubmUgbGlzZW5zYXZ0YWxlbiwga2xpa2tlciBEZSBwjCAiRW5pZyIta25hcHBlbiBmb3IgjCBpbnN0YWxsZXJlIHByb2dyYW12YXJlbi4gSHZpcyBEZSBpa2tlIGVyIGVuaWcsIGtsaWtrZXIgRGUgcIwgIklra2UgZW5pZyIu</data>
-			<key>ID</key>
-			<string>5016</string>
-			<key>Name</key>
-			<string>Norwegian</string>
-		</dict>
-	</array>
-	<key>TEXT</key>
-	<array>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>APPLICATION_LICENSE_TEXT</data>
-			<key>ID</key>
-			<string>5000</string>
-			<key>Name</key>
-			<string>English SLA</string>
-		</dict>
-	</array>
-	<key>TMPL</key>
-	<array>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>E0RlZmF1bHQgTGFuZ3VhZ2UgSUREV1JEBUNvdW50T0NOVAQqKioqTFNUQwtzeXMgbGFuZyBJRERXUkQebG9jYWwgcmVzIElEIChvZmZzZXQgZnJvbSA1MDAwRFdSRBAyLWJ5dGUgbGFuZ3VhZ2U/RFdSRAQqKioqTFNURQ==</data>
-			<key>ID</key>
-			<string>128</string>
-			<key>Name</key>
-			<string>LPic</string>
-		</dict>
-	</array>
-	<key>plst</key>
-	<array>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0050</string>
-			<key>Data</key>
-			<data>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</data>
-			<key>ID</key>
-			<string>0</string>
-			<key>Name</key>
-			<string></string>
-		</dict>
-	</array>
-	<key>styl</key>
-	<array>
-		<dict>
-			<key>Attributes</key>
-			<string>0x0000</string>
-			<key>Data</key>
-			<data>AAMAAAAAAAwACQAUAAAAAAAAAAAAAAAAACcADAAJABQBAAAAAAAAAAAAAAAAKgAMAAkAFAAAAAAAAAAAAAA=</data>
-			<key>ID</key>
-			<string>5000</string>
-			<key>Name</key>
-			<string>English SLA</string>
-		</dict>
-	</array>
-</dict>
-</plist>
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/postinstall.template	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-#!/usr/bin/env sh
-
-chown root:wheel "INSTALL_LOCATION"
-chmod a+rX "INSTALL_LOCATION"
-chmod +r "APP_LOCATION/"*.jar
-
-exit 0
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/preinstall.template	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-#!/usr/bin/env sh
-
-if [ ! -d "INSTALL_LOCATION" ]
-then
-    mkdir -p "INSTALL_LOCATION"
-fi
-
-exit 0
--- a/src/jdk.jpackage/macosx/classes/module-info.java.extra	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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.
- */
-
-provides jdk.jpackage.internal.Bundler with
-    jdk.jpackage.internal.MacAppBundler,
-    jdk.jpackage.internal.MacAppStoreBundler,
-    jdk.jpackage.internal.MacDmgBundler,
-    jdk.jpackage.internal.MacPkgBundler;
-
--- a/src/jdk.jpackage/macosx/native/jpackageapplauncher/main.m	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.
- */
-
-#import <Cocoa/Cocoa.h>
-#include <dlfcn.h>
-#include <unistd.h>
-
-typedef bool (*start_launcher)(int argc, char* argv[]);
-typedef void (*stop_launcher)();
-
-int main(int argc, char *argv[]) {
-#if !__has_feature(objc_arc)
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-#endif
-
-    int result = 1;
-
-    @try {
-        setlocale(LC_ALL, "en_US.utf8");
-
-        NSBundle *mainBundle = [NSBundle mainBundle];
-        NSString *mainBundlePath = [mainBundle bundlePath];
-        NSString *libraryName = [mainBundlePath stringByAppendingPathComponent:@"Contents/MacOS/libapplauncher.dylib"];
-
-        void* library = dlopen([libraryName UTF8String], RTLD_LAZY);
-
-        if (library == NULL) {
-            NSLog(@"%@ not found.\n", libraryName);
-        }
-
-        if (library != NULL) {
-            start_launcher start =
-                    (start_launcher)dlsym(library, "start_launcher");
-            stop_launcher stop =
-                    (stop_launcher)dlsym(library, "stop_launcher");
-
-            if (start != NULL && stop != NULL) {
-                if (start(argc, argv) == true) {
-                    result = 0;
-                    stop();
-                }
-            } else if (start == NULL) {
-                NSLog(@"start_launcher not found in %@.\n", libraryName);
-            } else {
-                NSLog(@"stop_launcher not found in %@.\n", libraryName);
-            }
-            dlclose(library);
-        }
-    } @catch (NSException *exception) {
-        NSLog(@"%@: %@", exception, [exception callStackSymbols]);
-        result = 1;
-    }
-
-#if !__has_feature(objc_arc)
-    [pool drain];
-#endif
-
-    return result;
-}
--- a/src/jdk.jpackage/macosx/native/libapplauncher/MacPlatform.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef MACPLATFORM_H
-#define MACPLATFORM_H
-
-#include "Platform.h"
-#include "PosixPlatform.h"
-
-class MacPlatform : virtual public Platform, PosixPlatform {
-private:
-    bool UsePListForConfigFile();
-
-protected:
-    virtual TString getTmpDirString();
-
-public:
-    MacPlatform(void);
-    virtual ~MacPlatform(void);
-
-public:
-    virtual void ShowMessage(TString title, TString description);
-    virtual void ShowMessage(TString description);
-
-    virtual TCHAR* ConvertStringToFileSystemString(
-            TCHAR* Source, bool &release);
-    virtual TCHAR* ConvertFileSystemStringToString(
-            TCHAR* Source, bool &release);
-
-    virtual TString GetPackageRootDirectory();
-    virtual TString GetAppDataDirectory();
-    virtual TString GetBundledJavaLibraryFileName(TString RuntimePath);
-    virtual TString GetAppName();
-
-    TString GetPackageAppDirectory();
-    TString GetPackageLauncherDirectory();
-    TString GetPackageRuntimeBinDirectory();
-
-    virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
-    virtual TString GetModuleFileName();
-
-    virtual bool IsMainThread();
-    virtual TPlatformNumber GetMemorySize();
-
-    virtual std::map<TString, TString> GetKeys();
-};
-
-
-#endif // MACPLATFORM_H
--- a/src/jdk.jpackage/macosx/native/libapplauncher/MacPlatform.mm	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,505 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "Platform.h"
-
-#include "MacPlatform.h"
-#include "Helpers.h"
-#include "Package.h"
-#include "PropertyFile.h"
-#include "IniFile.h"
-
-#include <sys/sysctl.h>
-#include <pthread.h>
-#include <vector>
-#include <signal.h>
-#include <mach-o/dyld.h>
-
-#import <Foundation/Foundation.h>
-#import <AppKit/NSRunningApplication.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <CoreFoundation/CFString.h>
-
-#ifdef __OBJC__
-#import <Cocoa/Cocoa.h>
-#endif //__OBJC__
-
-#define MAC_JPACKAGE_TMP_DIR \
-        "/Library/Application Support/Java/JPackage/tmp"
-
-NSString* StringToNSString(TString Value) {
-    NSString* result = [NSString stringWithCString : Value.c_str()
-            encoding : [NSString defaultCStringEncoding]];
-    return result;
-}
-
-FileSystemStringToString::FileSystemStringToString(const TCHAR* value) {
-    bool release = false;
-    PlatformString lvalue = PlatformString(value);
-    Platform& platform = Platform::GetInstance();
-    TCHAR* buffer = platform.ConvertFileSystemStringToString(lvalue, release);
-    FData = buffer;
-
-    if (buffer != NULL && release == true) {
-        delete[] buffer;
-    }
-}
-
-FileSystemStringToString::operator TString() {
-    return FData;
-}
-
-StringToFileSystemString::StringToFileSystemString(const TString &value) {
-    FRelease = false;
-    PlatformString lvalue = PlatformString(value);
-    Platform& platform = Platform::GetInstance();
-    FData = platform.ConvertStringToFileSystemString(lvalue, FRelease);
-}
-
-StringToFileSystemString::~StringToFileSystemString() {
-    if (FRelease == true) {
-        delete[] FData;
-    }
-}
-
-StringToFileSystemString::operator TCHAR* () {
-    return FData;
-}
-
-MacPlatform::MacPlatform(void) : Platform(), PosixPlatform() {
-}
-
-MacPlatform::~MacPlatform(void) {
-}
-
-TString MacPlatform::GetPackageAppDirectory() {
-    return FilePath::IncludeTrailingSeparator(
-            GetPackageRootDirectory()) + _T("app");
-}
-
-TString MacPlatform::GetPackageLauncherDirectory() {
-    return FilePath::IncludeTrailingSeparator(
-            GetPackageRootDirectory()) + _T("MacOS");
-}
-
-TString MacPlatform::GetPackageRuntimeBinDirectory() {
-    return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory()) +
-            _T("runtime/Contents/Home/bin");
-}
-
-bool MacPlatform::UsePListForConfigFile() {
-    return FilePath::FileExists(GetConfigFileName()) == false;
-}
-
-void MacPlatform::ShowMessage(TString Title, TString Description) {
-    NSString *ltitle = StringToNSString(Title);
-    NSString *ldescription = StringToNSString(Description);
-
-    NSLog(@"%@:%@", ltitle, ldescription);
-}
-
-void MacPlatform::ShowMessage(TString Description) {
-    TString appname = GetModuleFileName();
-    appname = FilePath::ExtractFileName(appname);
-    ShowMessage(appname, Description);
-}
-
-TString MacPlatform::getTmpDirString() {
-    return TString(MAC_JPACKAGE_TMP_DIR);
-}
-
-TCHAR* MacPlatform::ConvertStringToFileSystemString(TCHAR* Source,
-        bool &release) {
-    TCHAR* result = NULL;
-    release = false;
-    CFStringRef StringRef = CFStringCreateWithCString(kCFAllocatorDefault,
-            Source, kCFStringEncodingUTF8);
-
-    if (StringRef != NULL) {
-        @ try {
-            CFIndex length =
-                    CFStringGetMaximumSizeOfFileSystemRepresentation(StringRef);
-            result = new char[length + 1];
-            if (result != NULL) {
-                if (CFStringGetFileSystemRepresentation(StringRef,
-                        result, length)) {
-                    release = true;
-                } else {
-                    delete[] result;
-                    result = NULL;
-                }
-            }
-        }
-        @finally
-        {
-            CFRelease(StringRef);
-        }
-    }
-
-    return result;
-}
-
-TCHAR* MacPlatform::ConvertFileSystemStringToString(TCHAR* Source,
-        bool &release) {
-    TCHAR* result = NULL;
-    release = false;
-    CFStringRef StringRef = CFStringCreateWithFileSystemRepresentation(
-            kCFAllocatorDefault, Source);
-
-    if (StringRef != NULL) {
-        @ try {
-            CFIndex length = CFStringGetLength(StringRef);
-
-            if (length > 0) {
-                CFIndex maxSize = CFStringGetMaximumSizeForEncoding(
-                        length, kCFStringEncodingUTF8);
-
-                result = new char[maxSize + 1];
-                if (result != NULL) {
-                    if (CFStringGetCString(StringRef, result, maxSize,
-                            kCFStringEncodingUTF8) == true) {
-                        release = true;
-                    } else {
-                        delete[] result;
-                        result = NULL;
-                    }
-                }
-            }
-        }
-        @finally
-        {
-            CFRelease(StringRef);
-        }
-    }
-
-    return result;
-}
-
-TString MacPlatform::GetPackageRootDirectory() {
-    NSBundle *mainBundle = [NSBundle mainBundle];
-    NSString *mainBundlePath = [mainBundle bundlePath];
-    NSString *contentsPath =
-            [mainBundlePath stringByAppendingString : @"/Contents"];
-    TString result = [contentsPath UTF8String];
-    return result;
-}
-
-TString MacPlatform::GetAppDataDirectory() {
-    TString result;
-    NSArray *paths = NSSearchPathForDirectoriesInDomains(
-            NSApplicationSupportDirectory, NSUserDomainMask, YES);
-    NSString *applicationSupportDirectory = [paths firstObject];
-    result = [applicationSupportDirectory UTF8String];
-    return result;
-}
-
-TString MacPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) {
-    TString result;
-
-    // first try lib/, then lib/jli
-    result = FilePath::IncludeTrailingSeparator(RuntimePath) +
-            _T("Contents/Home/lib/libjli.dylib");
-
-    if (FilePath::FileExists(result) == false) {
-        result = FilePath::IncludeTrailingSeparator(RuntimePath) +
-                _T("Contents/Home/lib/jli/libjli.dylib");
-
-        if (FilePath::FileExists(result) == false) {
-            // cannot find
-            NSLog(@"Cannot find libjli.dysym!");
-            result = _T("");
-        }
-    }
-
-    return result;
-}
-
-TString MacPlatform::GetAppName() {
-    NSString *appName = [[NSProcessInfo processInfo] processName];
-    TString result = [appName UTF8String];
-    return result;
-}
-
-void PosixProcess::Cleanup() {
-    if (FOutputHandle != 0) {
-        close(FOutputHandle);
-        FOutputHandle = 0;
-    }
-
-    if (FInputHandle != 0) {
-        close(FInputHandle);
-        FInputHandle = 0;
-    }
-
-    sigaction(SIGINT, &savintr, (struct sigaction *) 0);
-    sigaction(SIGQUIT, &savequit, (struct sigaction *) 0);
-    sigprocmask(SIG_SETMASK, &saveblock, (sigset_t *) 0);
-}
-
-#define PIPE_READ 0
-#define PIPE_WRITE 1
-
-bool PosixProcess::Execute(const TString Application,
-        const std::vector<TString> Arguments, bool AWait) {
-    bool result = false;
-
-    if (FRunning == false) {
-        FRunning = true;
-
-        int handles[2];
-
-        if (pipe(handles) == -1) {
-            return false;
-        }
-
-        struct sigaction sa;
-        sa.sa_handler = SIG_IGN;
-        sigemptyset(&sa.sa_mask);
-        sa.sa_flags = 0;
-        sigemptyset(&savintr.sa_mask);
-        sigemptyset(&savequit.sa_mask);
-        sigaction(SIGINT, &sa, &savintr);
-        sigaction(SIGQUIT, &sa, &savequit);
-        sigaddset(&sa.sa_mask, SIGCHLD);
-        sigprocmask(SIG_BLOCK, &sa.sa_mask, &saveblock);
-
-        FChildPID = fork();
-
-        // PID returned by vfork is 0 for the child process and the
-        // PID of the child process for the parent.
-        if (FChildPID == -1) {
-            // Error
-            TString message = PlatformString::Format(
-                    _T("Error: Unable to create process %s"),
-                    Application.data());
-            throw Exception(message);
-        } else if (FChildPID == 0) {
-            Cleanup();
-            TString command = Application;
-
-            for (std::vector<TString>::const_iterator iterator =
-                    Arguments.begin(); iterator != Arguments.end();
-                    iterator++) {
-                command += TString(_T(" ")) + *iterator;
-            }
-#ifdef DEBUG
-            printf("%s\n", command.data());
-#endif // DEBUG
-
-            dup2(handles[PIPE_READ], STDIN_FILENO);
-            dup2(handles[PIPE_WRITE], STDOUT_FILENO);
-
-            close(handles[PIPE_READ]);
-            close(handles[PIPE_WRITE]);
-
-            execl("/bin/sh", "sh", "-c", command.data(), (char *) 0);
-
-            _exit(127);
-        } else {
-            FOutputHandle = handles[PIPE_READ];
-            FInputHandle = handles[PIPE_WRITE];
-
-            if (AWait == true) {
-                ReadOutput();
-                Wait();
-                Cleanup();
-                FRunning = false;
-                result = true;
-            } else {
-                result = true;
-            }
-        }
-    }
-
-    return result;
-}
-
-void AppendPListArrayToIniFile(NSDictionary *infoDictionary,
-        IniFile *result, TString Section) {
-    NSString *sectionKey =
-            [NSString stringWithUTF8String : PlatformString(Section).toMultibyte()];
-    NSDictionary *array = [infoDictionary objectForKey : sectionKey];
-
-    for (id option in array) {
-        if ([option isKindOfClass : [NSString class]]) {
-            TString arg = [option UTF8String];
-
-            TString name;
-            TString value;
-
-            if (Helpers::SplitOptionIntoNameValue(arg, name, value) == true) {
-                result->Append(Section, name, value);
-            }
-        }
-    }
-}
-
-void AppendPListDictionaryToIniFile(NSDictionary *infoDictionary,
-        IniFile *result, TString Section, bool FollowSection = true) {
-    NSDictionary *dictionary = NULL;
-
-    if (FollowSection == true) {
-        NSString *sectionKey = [NSString stringWithUTF8String : PlatformString(
-                Section).toMultibyte()];
-        dictionary = [infoDictionary objectForKey : sectionKey];
-    } else {
-        dictionary = infoDictionary;
-    }
-
-    for (id key in dictionary) {
-        id option = [dictionary valueForKey : key];
-
-        if ([key isKindOfClass : [NSString class]] &&
-                [option isKindOfClass : [NSString class]]) {
-            TString name = [key UTF8String];
-            TString value = [option UTF8String];
-            result->Append(Section, name, value);
-        }
-    }
-}
-
-// Convert parts of the info.plist to the INI format the rest of the jpackage
-// uses unless a jpackage config file exists.
-ISectionalPropertyContainer* MacPlatform::GetConfigFile(TString FileName) {
-    IniFile* result = new IniFile();
-    if (result == NULL) {
-        return NULL;
-    }
-
-    if (UsePListForConfigFile() == false) {
-        result->LoadFromFile(FileName);
-    } else {
-        NSBundle *mainBundle = [NSBundle mainBundle];
-        NSDictionary *infoDictionary = [mainBundle infoDictionary];
-        std::map<TString, TString> keys = GetKeys();
-
-        // JPackage options.
-        AppendPListDictionaryToIniFile(infoDictionary, result,
-                keys[CONFIG_SECTION_APPLICATION], false);
-
-        // jvmargs
-        AppendPListArrayToIniFile(infoDictionary, result,
-                keys[CONFIG_SECTION_JAVAOPTIONS]);
-
-        // Generate AppCDS Cache
-        AppendPListDictionaryToIniFile(infoDictionary, result,
-                keys[CONFIG_SECTION_APPCDSJAVAOPTIONS]);
-        AppendPListDictionaryToIniFile(infoDictionary, result,
-                keys[CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS]);
-
-        // args
-        AppendPListArrayToIniFile(infoDictionary, result,
-                keys[CONFIG_SECTION_ARGOPTIONS]);
-    }
-
-    return result;
-}
-
-TString GetModuleFileNameOSX() {
-    Dl_info module_info;
-    if (dladdr(reinterpret_cast<void*> (GetModuleFileNameOSX),
-            &module_info) == 0) {
-        // Failed to find the symbol we asked for.
-        return std::string();
-    }
-    return TString(module_info.dli_fname);
-}
-
-TString MacPlatform::GetModuleFileName() {
-    TString result;
-    DynamicBuffer<TCHAR> buffer(MAX_PATH);
-    uint32_t size = buffer.GetSize();
-
-    if (_NSGetExecutablePath(buffer.GetData(), &size) == 0) {
-        result = FileSystemStringToString(buffer.GetData());
-    }
-
-    return result;
-}
-
-bool MacPlatform::IsMainThread() {
-    bool result = (pthread_main_np() == 1);
-    return result;
-}
-
-TPlatformNumber MacPlatform::GetMemorySize() {
-    unsigned long long memory = [[NSProcessInfo processInfo] physicalMemory];
-
-    // Convert from bytes to megabytes.
-    TPlatformNumber result = memory / 1048576;
-
-    return result;
-}
-
-std::map<TString, TString> MacPlatform::GetKeys() {
-    std::map<TString, TString> keys;
-
-    if (UsePListForConfigFile() == false) {
-        return Platform::GetKeys();
-    } else {
-        keys.insert(std::map<TString, TString>::value_type(CONFIG_VERSION,
-                _T("app.version")));
-        keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINJAR_KEY,
-                _T("JavaMainJarName")));
-        keys.insert(std::map<TString,
-                TString>::value_type(CONFIG_MAINMODULE_KEY,
-                _T("JavaMainModuleName")));
-        keys.insert(std::map<TString, TString>::value_type(
-                CONFIG_MAINCLASSNAME_KEY, _T("JavaMainClassName")));
-        keys.insert(std::map<TString, TString>::value_type(
-                CONFIG_CLASSPATH_KEY, _T("JavaAppClasspath")));
-        keys.insert(std::map<TString, TString>::value_type(APP_NAME_KEY,
-                _T("CFBundleName")));
-        keys.insert(std::map<TString, TString>::value_type(JAVA_RUNTIME_KEY,
-                _T("JavaRuntime")));
-        keys.insert(std::map<TString,
-                TString>::value_type(JPACKAGE_APP_DATA_DIR,
-                _T("CFBundleIdentifier")));
-
-        keys.insert(std::map<TString, TString>::value_type(CONFIG_SPLASH_KEY,
-                _T("app.splash")));
-        keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_MEMORY,
-                _T("app.memory")));
-        keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_DEBUG,
-                _T("app.debug")));
-        keys.insert(std::map<TString, TString>::value_type(
-                CONFIG_APPLICATION_INSTANCE, _T("app.application.instance")));
-
-        keys.insert(std::map<TString, TString>::value_type(
-                CONFIG_SECTION_APPLICATION, _T("Application")));
-        keys.insert(std::map<TString, TString>::value_type(
-                CONFIG_SECTION_JAVAOPTIONS, _T("JavaOptions")));
-        keys.insert(std::map<TString, TString>::value_type(
-                CONFIG_SECTION_APPCDSJAVAOPTIONS, _T("AppCDSJavaOptions")));
-        keys.insert(std::map<TString, TString>::value_type(
-                CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS,
-                _T("AppCDSGenerateCacheJavaOptions")));
-        keys.insert(std::map<TString, TString>::value_type(
-                CONFIG_SECTION_ARGOPTIONS, _T("ArgOptions")));
-    }
-
-    return keys;
-}
--- a/src/jdk.jpackage/macosx/native/libapplauncher/PlatformDefs.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef PLATFORM_DEFS_H
-#define PLATFORM_DEFS_H
-
-#include <errno.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <dlfcn.h>
-#include <libgen.h>
-#include <string>
-
-using namespace std;
-
-#ifndef MAC
-#define MAC
-#endif
-
-#define _T(x) x
-
-typedef char TCHAR;
-typedef std::string TString;
-#define StringLength strlen
-
-typedef unsigned long DWORD;
-
-#define TRAILING_PATHSEPARATOR '/'
-#define BAD_TRAILING_PATHSEPARATOR '\\'
-#define PATH_SEPARATOR ':'
-#define BAD_PATH_SEPARATOR ';'
-#define MAX_PATH 1000
-
-typedef long TPlatformNumber;
-typedef pid_t TProcessID;
-
-#define HMODULE void*
-
-typedef void* Module;
-typedef void* Procedure;
-
-
-// StringToFileSystemString is a stack object. It's usage is
-// simply inline to convert a
-// TString to a file system string. Example:
-//
-// return dlopen(StringToFileSystemString(FileName), RTLD_LAZY);
-//
-class StringToFileSystemString {
-    // Prohibit Heap-Based StringToFileSystemString
-private:
-    static void *operator new(size_t size);
-    static void operator delete(void *ptr);
-
-private:
-    TCHAR* FData;
-    bool FRelease;
-
-public:
-    StringToFileSystemString(const TString &value);
-    ~StringToFileSystemString();
-
-    operator TCHAR* ();
-};
-
-
-// FileSystemStringToString is a stack object. It's usage is
-// simply inline to convert a
-// file system string to a TString. Example:
-//
-// DynamicBuffer<TCHAR> buffer(MAX_PATH);
-// if (readlink("/proc/self/exe", buffer.GetData(), MAX_PATH) != -1)
-//    result = FileSystemStringToString(buffer.GetData());
-//
-class FileSystemStringToString {
-    // Prohibit Heap-Based FileSystemStringToString
-private:
-    static void *operator new(size_t size);
-    static void operator delete(void *ptr);
-
-private:
-    TString FData;
-
-public:
-    FileSystemStringToString(const TCHAR* value);
-
-    operator TString ();
-};
-
-#endif // PLATFORM_DEFS_H
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractAppImageBuilder.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,191 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.text.MessageFormat;
-import java.util.List;
-import java.util.Map;
-import java.util.ResourceBundle;
-import java.util.ArrayList;
-
-import jdk.jpackage.internal.resources.ResourceLocator;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-/*
- * AbstractAppImageBuilder
- *     This is sub-classed by each of the platform dependent AppImageBuilder
- * classes, and contains resource processing code common to all platforms.
- */
-
-public abstract class AbstractAppImageBuilder {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MainResources");
-
-    private final Path root;
-
-    public AbstractAppImageBuilder(Map<String, Object> unused, Path root) {
-        this.root = root;
-    }
-
-    public InputStream getResourceAsStream(String name) {
-        return ResourceLocator.class.getResourceAsStream(name);
-    }
-
-    public abstract void prepareApplicationFiles(
-            Map<String, ? super Object> params) throws IOException;
-    public abstract void prepareJreFiles(
-            Map<String, ? super Object> params) throws IOException;
-    public abstract Path getAppDir();
-    public abstract Path getAppModsDir();
-
-    public Path getRuntimeRoot() {
-        return this.root;
-    }
-
-    protected void copyEntry(Path appDir, File srcdir, String fname)
-            throws IOException {
-        Path dest = appDir.resolve(fname);
-        Files.createDirectories(dest.getParent());
-        File src = new File(srcdir, fname);
-        if (src.isDirectory()) {
-            IOUtils.copyRecursive(src.toPath(), dest);
-        } else {
-            Files.copy(src.toPath(), dest);
-        }
-    }
-
-    public void writeCfgFile(Map<String, ? super Object> params,
-            File cfgFileName) throws IOException {
-        cfgFileName.getParentFile().mkdirs();
-        cfgFileName.delete();
-        File mainJar = JLinkBundlerHelper.getMainJar(params);
-        ModFile.ModType mainJarType = ModFile.ModType.Unknown;
-
-        if (mainJar != null) {
-            mainJarType = new ModFile(mainJar).getModType();
-        }
-
-        String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
-
-        try (PrintStream out = new PrintStream(cfgFileName)) {
-
-            out.println("[Application]");
-            out.println("app.name=" + APP_NAME.fetchFrom(params));
-            out.println("app.version=" + VERSION.fetchFrom(params));
-            out.println("app.runtime=" + getCfgRuntimeDir());
-            out.println("app.identifier=" + IDENTIFIER.fetchFrom(params));
-            out.println("app.classpath="
-                    + getCfgClassPath(CLASSPATH.fetchFrom(params)));
-
-            // The main app is required to be a jar, modular or unnamed.
-            if (mainModule != null &&
-                    (mainJarType == ModFile.ModType.Unknown ||
-                    mainJarType == ModFile.ModType.ModularJar)) {
-                out.println("app.mainmodule=" + mainModule);
-            } else {
-                String mainClass =
-                        StandardBundlerParam.MAIN_CLASS.fetchFrom(params);
-                // If the app is contained in an unnamed jar then launch it the
-                // legacy way and the main class string must be
-                // of the format com/foo/Main
-                if (mainJar != null) {
-                    out.println("app.mainjar=" + getCfgAppDir()
-                            + mainJar.toPath().getFileName().toString());
-                }
-                if (mainClass != null) {
-                    out.println("app.mainclass="
-                            + mainClass.replace("\\", "/"));
-                }
-            }
-
-            out.println();
-            out.println("[JavaOptions]");
-            List<String> jvmargs = JAVA_OPTIONS.fetchFrom(params);
-            for (String arg : jvmargs) {
-                out.println(arg);
-            }
-            Path modsDir = getAppModsDir();
-
-            if (modsDir != null && modsDir.toFile().exists()) {
-                out.println("--module-path");
-                out.println(getCfgAppDir().replace("\\","/") + "mods");
-            }
-
-            out.println();
-            out.println("[ArgOptions]");
-            List<String> args = ARGUMENTS.fetchFrom(params);
-            for (String arg : args) {
-                if (arg.endsWith("=") &&
-                        (arg.indexOf("=") == arg.lastIndexOf("="))) {
-                    out.print(arg.substring(0, arg.length() - 1));
-                    out.println("\\=");
-                } else {
-                    out.println(arg);
-                }
-            }
-        }
-    }
-
-    File getRuntimeImageDir(File runtimeImageTop) {
-        return runtimeImageTop;
-    }
-
-    protected String getCfgAppDir() {
-        return "$ROOTDIR" + File.separator
-                + getAppDir().getFileName() + File.separator;
-    }
-
-    protected String getCfgRuntimeDir() {
-        return "$ROOTDIR" + File.separator + "runtime";
-    }
-
-    String getCfgClassPath(String classpath) {
-        String cfgAppDir = getCfgAppDir();
-
-        StringBuilder sb = new StringBuilder();
-        for (String path : classpath.split("[:;]")) {
-            if (path.length() > 0) {
-                sb.append(cfgAppDir);
-                sb.append(path);
-                sb.append(File.pathSeparator);
-            }
-        }
-        if (sb.length() > 0) {
-            sb.deleteCharAt(sb.length() - 1);
-        }
-        return sb.toString();
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.File;
-import java.io.IOException;
-import java.util.Map;
-
-
-/**
- * AbstractBundler
- *
- * This is the base class all bundlers extend from.
- * It contains methods and parameters common to all bundlers.
- * The concrete implementations are in the platform specific bundlers.
- */
-abstract class AbstractBundler implements Bundler {
-
-    static final BundlerParamInfo<File> IMAGES_ROOT =
-            new StandardBundlerParam<>(
-            "imagesRoot",
-            File.class,
-            params -> new File(
-                StandardBundlerParam.TEMP_ROOT.fetchFrom(params), "images"),
-            (s, p) -> null);
-
-    @Override
-    public String toString() {
-        return getName();
-    }
-
-    @Override
-    public void cleanup(Map<String, ? super Object> params) {
-        try {
-            IOUtils.deleteRecursive(
-                    StandardBundlerParam.TEMP_ROOT.fetchFrom(params));
-        } catch (IOException e) {
-            Log.verbose(e.getMessage());
-        }
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AbstractImageBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.text.MessageFormat;
-import java.util.Map;
-import java.util.ResourceBundle;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.io.File;
-import java.io.IOException;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-/**
- * AbstractImageBundler
- *
- * This is the base class for each of the Application Image Bundlers.
- *
- * It contains methods and parameters common to all Image Bundlers.
- *
- * Application Image Bundlers are created in "create-app-image" mode,
- * or as an intermediate step in "create-installer" mode.
- *
- * The concrete implementations are in the platform specific Bundlers.
- */
-public abstract class AbstractImageBundler extends AbstractBundler {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MainResources");
-
-    public void imageBundleValidation(Map<String, ? super Object> params)
-             throws ConfigException {
-        StandardBundlerParam.validateMainClassInfoFromAppResources(params);
-
-    }
-
-    protected File createRoot(Map<String, ? super Object> params,
-            File outputDirectory, boolean dependentTask, String name)
-            throws PackagerException {
-
-        IOUtils.writableOutputDir(outputDirectory.toPath());
-
-        if (!dependentTask) {
-            Log.verbose(MessageFormat.format(
-                    I18N.getString("message.creating-app-bundle"),
-                    name, outputDirectory.getAbsolutePath()));
-        }
-
-        // NAME will default to CLASS, so the real problem is no MAIN_CLASS
-        if (name == null) {
-            throw new PackagerException("ERR_NoMainClass");
-        }
-
-        // Create directory structure
-        File rootDirectory = new File(outputDirectory, name);
-
-        if (rootDirectory.exists()) {
-            throw new PackagerException("error.root-exists",
-                    rootDirectory.getAbsolutePath());
-        }
-
-        rootDirectory.mkdirs();
-
-        return rootDirectory;
-    }
-
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AddLauncherArguments.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.io.File;
-import jdk.jpackage.internal.Arguments.CLIOptions;
-
-/*
- * AddLauncherArguments
- *
- * Processes a add-launcher properties file to create the Map of
- * bundle params applicable to the add-launcher:
- *
- * BundlerParams p = (new AddLauncherArguments(file)).getLauncherMap();
- *
- * A add-launcher is another executable program generated by either the
- * create-app-image mode or the create-installer mode.
- * The add-launcher may be the same program with different configuration,
- * or a completely different program created from the same files.
- *
- * There may be multiple add-launchers, each created by using the
- * command line arg "--add-launcher <file path>
- *
- * The add-launcher properties file may have any of:
- *
- * appVersion
- * module
- * main-jar
- * main-class
- * icon
- * arguments
- * java-options
- * win-console
- * linux-app-category
- *
- */
-class AddLauncherArguments {
-
-    private final String name;
-    private final String filename;
-    private Map<String, String> allArgs;
-    private Map<String, ? super Object> bundleParams;
-
-    AddLauncherArguments(String name, String filename) {
-        this.name = name;
-        this.filename = filename;
-    }
-
-    private void initLauncherMap() {
-        if (bundleParams != null) {
-            return;
-        }
-
-        allArgs = Arguments.getPropertiesFromFile(filename);
-        allArgs.put(CLIOptions.NAME.getId(), name);
-
-        bundleParams = new HashMap<>();
-        String mainJar = getOptionValue(CLIOptions.MAIN_JAR);
-        String mainClass = getOptionValue(CLIOptions.APPCLASS);
-        String module = getOptionValue(CLIOptions.MODULE);
-
-        if (module != null && mainClass != null) {
-            putUnlessNull(bundleParams, CLIOptions.MODULE.getId(),
-                    module + "/" + mainClass);
-        } else if (module != null) {
-            putUnlessNull(bundleParams, CLIOptions.MODULE.getId(),
-                    module);
-        } else {
-            putUnlessNull(bundleParams, CLIOptions.MAIN_JAR.getId(),
-                    mainJar);
-            putUnlessNull(bundleParams, CLIOptions.APPCLASS.getId(),
-                    mainClass);
-        }
-
-        putUnlessNull(bundleParams, CLIOptions.NAME.getId(),
-                getOptionValue(CLIOptions.NAME));
-
-        putUnlessNull(bundleParams, CLIOptions.VERSION.getId(),
-                getOptionValue(CLIOptions.VERSION));
-
-        putUnlessNull(bundleParams, CLIOptions.RELEASE.getId(),
-                getOptionValue(CLIOptions.RELEASE));
-
-        putUnlessNull(bundleParams, CLIOptions.LINUX_CATEGORY.getId(),
-                getOptionValue(CLIOptions.LINUX_CATEGORY));
-
-        putUnlessNull(bundleParams,
-                CLIOptions.WIN_CONSOLE_HINT.getId(),
-                getOptionValue(CLIOptions.WIN_CONSOLE_HINT));
-
-        String value = getOptionValue(CLIOptions.ICON);
-        putUnlessNull(bundleParams, CLIOptions.ICON.getId(),
-                (value == null) ? null : new File(value));
-
-        // "arguments" and "java-options" even if value is null:
-        if (allArgs.containsKey(CLIOptions.ARGUMENTS.getId())) {
-            String argumentStr = getOptionValue(CLIOptions.ARGUMENTS);
-            bundleParams.put(CLIOptions.ARGUMENTS.getId(),
-                    Arguments.getArgumentList(argumentStr));
-        }
-
-        if (allArgs.containsKey(CLIOptions.JAVA_OPTIONS.getId())) {
-            String jvmargsStr = getOptionValue(CLIOptions.JAVA_OPTIONS);
-            bundleParams.put(CLIOptions.JAVA_OPTIONS.getId(),
-                    Arguments.getArgumentList(jvmargsStr));
-        }
-    }
-
-    private String getOptionValue(CLIOptions option) {
-        if (option == null || allArgs == null) {
-            return null;
-        }
-
-        String id = option.getId();
-
-        if (allArgs.containsKey(id)) {
-            return allArgs.get(id);
-        }
-
-        return null;
-    }
-
-    Map<String, ? super Object> getLauncherMap() {
-        initLauncherMap();
-        return bundleParams;
-    }
-
-    private void putUnlessNull(Map<String, ? super Object> params,
-            String param, Object value) {
-        if (value != null) {
-            params.put(param, value);
-        }
-    }
-
-    static Map<String, ? super Object> merge(
-            Map<String, ? super Object> original,
-            Map<String, ? super Object> additional) {
-        Map<String, ? super Object> tmp = new HashMap<>(original);
-        if (additional.containsKey(CLIOptions.MODULE.getId())) {
-            tmp.remove(CLIOptions.MAIN_JAR.getId());
-            tmp.remove(CLIOptions.APPCLASS.getId());
-        } else if (additional.containsKey(CLIOptions.MAIN_JAR.getId())) {
-            tmp.remove(CLIOptions.MODULE.getId());
-        }
-        if (additional.containsKey(CLIOptions.ARGUMENTS.getId())) {
-            // if add launcher properties file contains "arguments", even with
-            // null value, disregard the "arguments" from command line
-            tmp.remove(CLIOptions.ARGUMENTS.getId());
-        }
-        if (additional.containsKey(CLIOptions.JAVA_OPTIONS.getId())) {
-            // same thing for java-options
-            tmp.remove(CLIOptions.JAVA_OPTIONS.getId());
-        }
-        tmp.putAll(additional);
-        return tmp;
-    }
-
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 2019, 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.FileInputStream;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-public class AppImageFile {
-
-    // These values will be loaded from AppImage xml file.
-    private final String creatorVersion;
-    private final String creatorPlatform;
-    private final String launcherName;
-    private final List<String> addLauncherNames;
-
-    private final static String FILENAME = ".jpackage.xml";
-
-    private final static Map<Platform, String> PLATFORM_LABELS = Map.of(
-            Platform.LINUX, "linux", Platform.WINDOWS, "windows", Platform.MAC,
-            "macOS");
-
-
-    private AppImageFile() {
-        this(null, null, null, null);
-    }
-
-    private AppImageFile(String launcherName, List<String> addLauncherNames,
-            String creatorVersion, String creatorPlatform) {
-        this.launcherName = launcherName;
-        this.addLauncherNames = addLauncherNames;
-        this.creatorVersion = creatorVersion;
-        this.creatorPlatform = creatorPlatform;
-    }
-
-    /**
-     * Returns list of additional launchers configured for the application.
-     * Each item in the list is not null or empty string.
-     * Returns empty list for application without additional launchers.
-     */
-    List<String> getAddLauncherNames() {
-        return addLauncherNames;
-    }
-
-    /**
-     * Returns main application launcher name. Never returns null or empty value.
-     */
-    String getLauncherName() {
-        return launcherName;
-    }
-
-    void verifyCompatible() throws ConfigException {
-        // Just do nothing for now.
-    }
-
-    /**
-     * Returns path to application image info file.
-     * @param appImageDir - path to application image
-     */
-    public static Path getPathInAppImage(Path appImageDir) {
-        return appImageDir.resolve(FILENAME);
-    }
-
-    /**
-     * Saves file with application image info in application image.
-     * @param appImageDir - path to application image
-     * @throws IOException
-     */
-    static void save(Path appImageDir, Map<String, Object> params)
-            throws IOException {
-        IOUtils.createXml(getPathInAppImage(appImageDir), xml -> {
-            xml.writeStartElement("jpackage-state");
-            xml.writeAttribute("version", getVersion());
-            xml.writeAttribute("platform", getPlatform());
-
-            xml.writeStartElement("main-launcher");
-            xml.writeCharacters(APP_NAME.fetchFrom(params));
-            xml.writeEndElement();
-
-            List<Map<String, ? super Object>> addLaunchers =
-                ADD_LAUNCHERS.fetchFrom(params);
-
-            for (int i = 0; i < addLaunchers.size(); i++) {
-                Map<String, ? super Object> sl = addLaunchers.get(i);
-                xml.writeStartElement("add-launcher");
-                xml.writeCharacters(APP_NAME.fetchFrom(sl));
-                xml.writeEndElement();
-            }
-        });
-    }
-
-    /**
-     * Loads application image info from application image.
-     * @param appImageDir - path to application image
-     * @return valid info about application image or null
-     * @throws IOException
-     */
-    static AppImageFile load(Path appImageDir) throws IOException {
-        try {
-            Path path = getPathInAppImage(appImageDir);
-            DocumentBuilderFactory dbf =
-                    DocumentBuilderFactory.newDefaultInstance();
-            dbf.setFeature(
-                   "http://apache.org/xml/features/nonvalidating/load-external-dtd",
-                    false);
-            DocumentBuilder b = dbf.newDocumentBuilder();
-            Document doc = b.parse(new FileInputStream(path.toFile()));
-
-            XPath xPath = XPathFactory.newInstance().newXPath();
-
-            String mainLauncher = xpathQueryNullable(xPath,
-                    "/jpackage-state/main-launcher/text()", doc);
-            if (mainLauncher == null) {
-                // No main launcher, this is fatal.
-                return new AppImageFile();
-            }
-
-            List<String> addLaunchers = new ArrayList<String>();
-
-            String platform = xpathQueryNullable(xPath,
-                    "/jpackage-state/@platform", doc);
-
-            String version = xpathQueryNullable(xPath,
-                    "/jpackage-state/@version", doc);
-
-            NodeList launcherNameNodes = (NodeList) xPath.evaluate(
-                    "/jpackage-state/add-launcher/text()", doc,
-                    XPathConstants.NODESET);
-
-            for (int i = 0; i != launcherNameNodes.getLength(); i++) {
-                addLaunchers.add(launcherNameNodes.item(i).getNodeValue());
-            }
-
-            AppImageFile file = new AppImageFile(
-                    mainLauncher, addLaunchers, version, platform);
-            if (!file.isValid()) {
-                file = new AppImageFile();
-            }
-            return file;
-        } catch (ParserConfigurationException | SAXException ex) {
-            // Let caller sort this out
-            throw new IOException(ex);
-        } catch (XPathExpressionException ex) {
-            // This should never happen as XPath expressions should be correct
-            throw new RuntimeException(ex);
-        }
-    }
-
-    /**
-     * Returns list of launcher names configured for the application.
-     * The first item in the returned list is main launcher name.
-     * Following items in the list are names of additional launchers.
-     */
-    static List<String> getLauncherNames(Path appImageDir,
-            Map<String, ? super Object> params) {
-        List<String> launchers = new ArrayList<>();
-        try {
-            AppImageFile appImageInfo = AppImageFile.load(appImageDir);
-            if (appImageInfo != null) {
-                launchers.add(appImageInfo.getLauncherName());
-                launchers.addAll(appImageInfo.getAddLauncherNames());
-                return launchers;
-            }
-        } catch (IOException ioe) {
-            Log.verbose(ioe);
-        }
-
-        launchers.add(APP_NAME.fetchFrom(params));
-        ADD_LAUNCHERS.fetchFrom(params).stream().map(APP_NAME::fetchFrom).forEach(
-                launchers::add);
-        return launchers;
-    }
-
-    private static String xpathQueryNullable(XPath xPath, String xpathExpr,
-            Document xml) throws XPathExpressionException {
-        NodeList nodes = (NodeList) xPath.evaluate(xpathExpr, xml,
-                XPathConstants.NODESET);
-        if (nodes != null && nodes.getLength() > 0) {
-            return nodes.item(0).getNodeValue();
-        }
-        return null;
-    }
-
-    private static String getVersion() {
-        return System.getProperty("java.version");
-    }
-
-    private static String getPlatform() {
-        return PLATFORM_LABELS.get(Platform.getPlatform());
-    }
-
-    private boolean isValid() {
-        if (launcherName == null || launcherName.length() == 0 ||
-            addLauncherNames.indexOf("") != -1) {
-            // Some launchers have empty names. This is invalid.
-            return false;
-        }
-
-        // Add more validation.
-
-        return true;
-    }
-
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationLayout.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2019, 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.nio.file.Path;
-import java.util.Map;
-
-
-/**
- * Application directory layout.
- */
-public final class ApplicationLayout implements PathGroup.Facade<ApplicationLayout> {
-    enum PathRole {
-        RUNTIME, APP, LAUNCHERS, DESKTOP, APP_MODS, DLLS
-    }
-
-    ApplicationLayout(Map<Object, Path> paths) {
-        data = new PathGroup(paths);
-    }
-
-    private ApplicationLayout(PathGroup data) {
-        this.data = data;
-    }
-
-    @Override
-    public PathGroup pathGroup() {
-        return data;
-    }
-
-    @Override
-    public ApplicationLayout resolveAt(Path root) {
-        return new ApplicationLayout(pathGroup().resolveAt(root));
-    }
-
-    /**
-     * Path to launchers directory.
-     */
-    public Path launchersDirectory() {
-        return pathGroup().getPath(PathRole.LAUNCHERS);
-    }
-
-    /**
-     * Path to directory with dynamic libraries.
-     */
-    public Path dllDirectory() {
-        return pathGroup().getPath(PathRole.DLLS);
-    }
-
-    /**
-     * Path to application data directory.
-     */
-    public Path appDirectory() {
-        return pathGroup().getPath(PathRole.APP);
-    }
-
-    /**
-     * Path to Java runtime directory.
-     */
-    public Path runtimeDirectory() {
-        return pathGroup().getPath(PathRole.RUNTIME);
-    }
-
-    /**
-     * Path to application mods directory.
-     */
-    public Path appModsDirectory() {
-        return pathGroup().getPath(PathRole.APP_MODS);
-    }
-
-    /**
-     * Path to directory with application's desktop integration files.
-     */
-    public Path destktopIntegrationDirectory() {
-        return pathGroup().getPath(PathRole.DESKTOP);
-    }
-
-    static ApplicationLayout linuxAppImage() {
-        return new ApplicationLayout(Map.of(
-                PathRole.LAUNCHERS, Path.of("bin"),
-                PathRole.APP, Path.of("lib/app"),
-                PathRole.RUNTIME, Path.of("lib/runtime"),
-                PathRole.DESKTOP, Path.of("lib"),
-                PathRole.DLLS, Path.of("lib"),
-                PathRole.APP_MODS, Path.of("lib/app/mods")
-        ));
-    }
-
-    static ApplicationLayout windowsAppImage() {
-        return new ApplicationLayout(Map.of(
-                PathRole.LAUNCHERS, Path.of(""),
-                PathRole.APP, Path.of("app"),
-                PathRole.RUNTIME, Path.of("runtime"),
-                PathRole.DESKTOP, Path.of(""),
-                PathRole.DLLS, Path.of(""),
-                PathRole.APP_MODS, Path.of("app/mods")
-        ));
-    }
-
-    static ApplicationLayout macAppImage() {
-        return new ApplicationLayout(Map.of(
-                PathRole.LAUNCHERS, Path.of("Contents/MacOS"),
-                PathRole.APP, Path.of("Contents/app"),
-                PathRole.RUNTIME, Path.of("Contents/runtime"),
-                PathRole.DESKTOP, Path.of("Contents/Resources"),
-                PathRole.DLLS, Path.of("Contents/MacOS"),
-                PathRole.APP_MODS, Path.of("Contents/app/mods")
-        ));
-    }
-
-    public static ApplicationLayout platformAppImage() {
-        if (Platform.isWindows()) {
-            return windowsAppImage();
-        }
-
-        if (Platform.isLinux()) {
-            return linuxAppImage();
-        }
-
-        if (Platform.isMac()) {
-            return macAppImage();
-        }
-
-        throw Platform.throwUnknownPlatformError();
-    }
-
-    public static ApplicationLayout javaRuntime() {
-        return new ApplicationLayout(Map.of(PathRole.RUNTIME, Path.of("")));
-    }
-
-    private final PathGroup data;
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ArgAction.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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;
-
-@FunctionalInterface
-interface ArgAction {
-    void execute();
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,802 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Properties;
-import java.util.ResourceBundle;
-import java.util.jar.Attributes;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.stream.Stream;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Arguments
- *
- * This class encapsulates and processes the command line arguments,
- * in effect, implementing all the work of jpackage tool.
- *
- * The primary entry point, processArguments():
- * Processes and validates command line arguments, constructing DeployParams.
- * Validates the DeployParams, and generate the BundleParams.
- * Generates List of Bundlers from BundleParams valid for this platform.
- * Executes each Bundler in the list.
- */
-public class Arguments {
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MainResources");
-
-    private static final String FA_EXTENSIONS = "extension";
-    private static final String FA_CONTENT_TYPE = "mime-type";
-    private static final String FA_DESCRIPTION = "description";
-    private static final String FA_ICON = "icon";
-
-    // regexp for parsing args (for example, for additional launchers)
-    private static Pattern pattern = Pattern.compile(
-          "(?:(?:([\"'])(?:\\\\\\1|.)*?(?:\\1|$))|(?:\\\\[\"'\\s]|[^\\s]))++");
-
-    private DeployParams deployParams = null;
-
-    private int pos = 0;
-    private List<String> argList = null;
-
-    private List<CLIOptions> allOptions = null;
-
-    private String input = null;
-    private String output = null;
-
-    private boolean hasMainJar = false;
-    private boolean hasMainClass = false;
-    private boolean hasMainModule = false;
-    public boolean userProvidedBuildRoot = false;
-
-    private String buildRoot = null;
-    private String mainJarPath = null;
-
-    private static boolean runtimeInstaller = false;
-
-    private List<AddLauncherArguments> addLaunchers = null;
-
-    private static Map<String, CLIOptions> argIds = new HashMap<>();
-    private static Map<String, CLIOptions> argShortIds = new HashMap<>();
-
-    static {
-        // init maps for parsing arguments
-        (EnumSet.allOf(CLIOptions.class)).forEach(option -> {
-            argIds.put(option.getIdWithPrefix(), option);
-            if (option.getShortIdWithPrefix() != null) {
-                argShortIds.put(option.getShortIdWithPrefix(), option);
-            }
-        });
-    }
-
-    public Arguments(String[] args) {
-        argList = new ArrayList<String>(args.length);
-        for (String arg : args) {
-            argList.add(arg);
-        }
-        Log.verbose ("\njpackage argument list: \n" + argList + "\n");
-        pos = 0;
-
-        deployParams = new DeployParams();
-
-        allOptions = new ArrayList<>();
-
-        addLaunchers = new ArrayList<>();
-
-        output = Paths.get("").toAbsolutePath().toString();
-        deployParams.setOutput(new File(output));
-    }
-
-    // CLIOptions is public for DeployParamsTest
-    public enum CLIOptions {
-        PACKAGE_TYPE("type", "t", OptionCategories.PROPERTY, () -> {
-            context().deployParams.setTargetFormat(popArg());
-        }),
-
-        INPUT ("input", "i", OptionCategories.PROPERTY, () -> {
-            context().input = popArg();
-            setOptionValue("input", context().input);
-        }),
-
-        OUTPUT ("dest", "d", OptionCategories.PROPERTY, () -> {
-            context().output = popArg();
-            context().deployParams.setOutput(new File(context().output));
-        }),
-
-        DESCRIPTION ("description", OptionCategories.PROPERTY),
-
-        VENDOR ("vendor", OptionCategories.PROPERTY),
-
-        APPCLASS ("main-class", OptionCategories.PROPERTY, () -> {
-            context().hasMainClass = true;
-            setOptionValue("main-class", popArg());
-        }),
-
-        NAME ("name", "n", OptionCategories.PROPERTY),
-
-        VERBOSE ("verbose", OptionCategories.PROPERTY, () -> {
-            setOptionValue("verbose", true);
-            Log.setVerbose();
-        }),
-
-        RESOURCE_DIR("resource-dir",
-                OptionCategories.PROPERTY, () -> {
-            String resourceDir = popArg();
-            setOptionValue("resource-dir", resourceDir);
-        }),
-
-        ARGUMENTS ("arguments", OptionCategories.PROPERTY, () -> {
-            List<String> arguments = getArgumentList(popArg());
-            setOptionValue("arguments", arguments);
-        }),
-
-        ICON ("icon", OptionCategories.PROPERTY),
-
-        COPYRIGHT ("copyright", OptionCategories.PROPERTY),
-
-        LICENSE_FILE ("license-file", OptionCategories.PROPERTY),
-
-        VERSION ("app-version", OptionCategories.PROPERTY),
-
-        RELEASE ("linux-app-release", OptionCategories.PROPERTY),
-
-        JAVA_OPTIONS ("java-options", OptionCategories.PROPERTY, () -> {
-            List<String> args = getArgumentList(popArg());
-            args.forEach(a -> setOptionValue("java-options", a));
-        }),
-
-        FILE_ASSOCIATIONS ("file-associations",
-                OptionCategories.PROPERTY, () -> {
-            Map<String, ? super Object> args = new HashMap<>();
-
-            // load .properties file
-            Map<String, String> initialMap = getPropertiesFromFile(popArg());
-
-            String ext = initialMap.get(FA_EXTENSIONS);
-            if (ext != null) {
-                args.put(StandardBundlerParam.FA_EXTENSIONS.getID(), ext);
-            }
-
-            String type = initialMap.get(FA_CONTENT_TYPE);
-            if (type != null) {
-                args.put(StandardBundlerParam.FA_CONTENT_TYPE.getID(), type);
-            }
-
-            String desc = initialMap.get(FA_DESCRIPTION);
-            if (desc != null) {
-                args.put(StandardBundlerParam.FA_DESCRIPTION.getID(), desc);
-            }
-
-            String icon = initialMap.get(FA_ICON);
-            if (icon != null) {
-                args.put(StandardBundlerParam.FA_ICON.getID(), icon);
-            }
-
-            ArrayList<Map<String, ? super Object>> associationList =
-                new ArrayList<Map<String, ? super Object>>();
-
-            associationList.add(args);
-
-            // check that we really add _another_ value to the list
-            setOptionValue("file-associations", associationList);
-
-        }),
-
-        ADD_LAUNCHER ("add-launcher",
-                    OptionCategories.PROPERTY, () -> {
-            String spec = popArg();
-            String name = null;
-            String filename = spec;
-            if (spec.contains("=")) {
-                String[] values = spec.split("=", 2);
-                name = values[0];
-                filename = values[1];
-            }
-            context().addLaunchers.add(
-                new AddLauncherArguments(name, filename));
-        }),
-
-        TEMP_ROOT ("temp", OptionCategories.PROPERTY, () -> {
-            context().buildRoot = popArg();
-            context().userProvidedBuildRoot = true;
-            setOptionValue("temp", context().buildRoot);
-        }),
-
-        INSTALL_DIR ("install-dir", OptionCategories.PROPERTY),
-
-        PREDEFINED_APP_IMAGE ("app-image", OptionCategories.PROPERTY),
-
-        PREDEFINED_RUNTIME_IMAGE ("runtime-image", OptionCategories.PROPERTY),
-
-        MAIN_JAR ("main-jar",  OptionCategories.PROPERTY, () -> {
-            context().mainJarPath = popArg();
-            context().hasMainJar = true;
-            setOptionValue("main-jar", context().mainJarPath);
-        }),
-
-        MODULE ("module", "m", OptionCategories.MODULAR, () -> {
-            context().hasMainModule = true;
-            setOptionValue("module", popArg());
-        }),
-
-        ADD_MODULES ("add-modules", OptionCategories.MODULAR),
-
-        MODULE_PATH ("module-path", "p", OptionCategories.MODULAR),
-
-        BIND_SERVICES ("bind-services", OptionCategories.PROPERTY, () -> {
-            setOptionValue("bind-services", true);
-        }),
-
-        MAC_SIGN ("mac-sign", "s", OptionCategories.PLATFORM_MAC, () -> {
-            setOptionValue("mac-sign", true);
-        }),
-
-        MAC_BUNDLE_NAME ("mac-package-name", OptionCategories.PLATFORM_MAC),
-
-        MAC_BUNDLE_IDENTIFIER("mac-package-identifier",
-                    OptionCategories.PLATFORM_MAC),
-
-        MAC_BUNDLE_SIGNING_PREFIX ("mac-package-signing-prefix",
-                    OptionCategories.PLATFORM_MAC),
-
-        MAC_SIGNING_KEY_NAME ("mac-signing-key-user-name",
-                    OptionCategories.PLATFORM_MAC),
-
-        MAC_SIGNING_KEYCHAIN ("mac-signing-keychain",
-                    OptionCategories.PLATFORM_MAC),
-
-        MAC_APP_STORE_ENTITLEMENTS ("mac-app-store-entitlements",
-                    OptionCategories.PLATFORM_MAC),
-
-        WIN_MENU_HINT ("win-menu", OptionCategories.PLATFORM_WIN, () -> {
-            setOptionValue("win-menu", true);
-        }),
-
-        WIN_MENU_GROUP ("win-menu-group", OptionCategories.PLATFORM_WIN),
-
-        WIN_SHORTCUT_HINT ("win-shortcut",
-                OptionCategories.PLATFORM_WIN, () -> {
-            setOptionValue("win-shortcut", true);
-        }),
-
-        WIN_PER_USER_INSTALLATION ("win-per-user-install",
-                OptionCategories.PLATFORM_WIN, () -> {
-            setOptionValue("win-per-user-install", false);
-        }),
-
-        WIN_DIR_CHOOSER ("win-dir-chooser",
-                OptionCategories.PLATFORM_WIN, () -> {
-            setOptionValue("win-dir-chooser", true);
-        }),
-
-        WIN_UPGRADE_UUID ("win-upgrade-uuid",
-                OptionCategories.PLATFORM_WIN),
-
-        WIN_CONSOLE_HINT ("win-console", OptionCategories.PLATFORM_WIN, () -> {
-            setOptionValue("win-console", true);
-        }),
-
-        LINUX_BUNDLE_NAME ("linux-package-name",
-                OptionCategories.PLATFORM_LINUX),
-
-        LINUX_DEB_MAINTAINER ("linux-deb-maintainer",
-                OptionCategories.PLATFORM_LINUX),
-
-        LINUX_CATEGORY ("linux-app-category",
-                OptionCategories.PLATFORM_LINUX),
-
-        LINUX_RPM_LICENSE_TYPE ("linux-rpm-license-type",
-                OptionCategories.PLATFORM_LINUX),
-
-        LINUX_PACKAGE_DEPENDENCIES ("linux-package-deps",
-                OptionCategories.PLATFORM_LINUX),
-
-        LINUX_SHORTCUT_HINT ("linux-shortcut",
-                OptionCategories.PLATFORM_LINUX, () -> {
-            setOptionValue("linux-shortcut", true);
-        }),
-
-        LINUX_MENU_GROUP ("linux-menu-group", OptionCategories.PLATFORM_LINUX);
-
-        private final String id;
-        private final String shortId;
-        private final OptionCategories category;
-        private final ArgAction action;
-        private static Arguments argContext;
-
-        private CLIOptions(String id, OptionCategories category) {
-            this(id, null, category, null);
-        }
-
-        private CLIOptions(String id, String shortId,
-                           OptionCategories category) {
-            this(id, shortId, category, null);
-        }
-
-        private CLIOptions(String id,
-                OptionCategories category, ArgAction action) {
-            this(id, null, category, action);
-        }
-
-        private CLIOptions(String id, String shortId,
-                           OptionCategories category, ArgAction action) {
-            this.id = id;
-            this.shortId = shortId;
-            this.action = action;
-            this.category = category;
-        }
-
-        static void setContext(Arguments context) {
-            argContext = context;
-        }
-
-        public static Arguments context() {
-            if (argContext != null) {
-                return argContext;
-            } else {
-                throw new RuntimeException("Argument context is not set.");
-            }
-        }
-
-        public String getId() {
-            return this.id;
-        }
-
-        String getIdWithPrefix() {
-            return "--" + this.id;
-        }
-
-        String getShortIdWithPrefix() {
-            return this.shortId == null ? null : "-" + this.shortId;
-        }
-
-        void execute() {
-            if (action != null) {
-                action.execute();
-            } else {
-                defaultAction();
-            }
-        }
-
-        private void defaultAction() {
-            context().deployParams.addBundleArgument(id, popArg());
-        }
-
-        private static void setOptionValue(String option, Object value) {
-            context().deployParams.addBundleArgument(option, value);
-        }
-
-        private static String popArg() {
-            nextArg();
-            return (context().pos >= context().argList.size()) ?
-                            "" : context().argList.get(context().pos);
-        }
-
-        private static String getArg() {
-            return (context().pos >= context().argList.size()) ?
-                        "" : context().argList.get(context().pos);
-        }
-
-        private static void nextArg() {
-            context().pos++;
-        }
-
-        private static boolean hasNextArg() {
-            return context().pos < context().argList.size();
-        }
-    }
-
-    enum OptionCategories {
-        MODULAR,
-        PROPERTY,
-        PLATFORM_MAC,
-        PLATFORM_WIN,
-        PLATFORM_LINUX;
-    }
-
-    public boolean processArguments() {
-        try {
-
-            // init context of arguments
-            CLIOptions.setContext(this);
-
-            // parse cmd line
-            String arg;
-            CLIOptions option;
-            for (; CLIOptions.hasNextArg(); CLIOptions.nextArg()) {
-                arg = CLIOptions.getArg();
-                if ((option = toCLIOption(arg)) != null) {
-                    // found a CLI option
-                    allOptions.add(option);
-                    option.execute();
-                } else {
-                    throw new PackagerException("ERR_InvalidOption", arg);
-                }
-            }
-
-            if (hasMainJar && !hasMainClass) {
-                // try to get main-class from manifest
-                String mainClass = getMainClassFromManifest();
-                if (mainClass != null) {
-                    CLIOptions.setOptionValue(
-                            CLIOptions.APPCLASS.getId(), mainClass);
-                }
-            }
-
-            // display error for arguments that are not supported
-            // for current configuration.
-
-            validateArguments();
-
-            addResources(deployParams, input, mainJarPath);
-
-            List<Map<String, ? super Object>> launchersAsMap =
-                    new ArrayList<>();
-
-            for (AddLauncherArguments sl : addLaunchers) {
-                launchersAsMap.add(sl.getLauncherMap());
-            }
-
-            deployParams.addBundleArgument(
-                    StandardBundlerParam.ADD_LAUNCHERS.getID(),
-                    launchersAsMap);
-
-            // at this point deployParams should be already configured
-
-            deployParams.validate();
-
-            BundleParams bp = deployParams.getBundleParams();
-
-            // validate name(s)
-            ArrayList<String> usedNames = new ArrayList<String>();
-            usedNames.add(bp.getName()); // add main app name
-
-            for (AddLauncherArguments sl : addLaunchers) {
-                Map<String, ? super Object> slMap = sl.getLauncherMap();
-                String slName =
-                        (String) slMap.get(Arguments.CLIOptions.NAME.getId());
-                if (slName == null) {
-                    throw new PackagerException("ERR_NoAddLauncherName");
-                }
-                // same rules apply to additional launcher names as app name
-                DeployParams.validateName(slName, false);
-                for (String usedName : usedNames) {
-                    if (slName.equals(usedName)) {
-                        throw new PackagerException("ERR_NoUniqueName");
-                    }
-                }
-                usedNames.add(slName);
-            }
-            if (runtimeInstaller && bp.getName() == null) {
-                throw new PackagerException("ERR_NoJreInstallerName");
-            }
-
-            generateBundle(bp.getBundleParamsAsMap());
-            return true;
-        } catch (Exception e) {
-            if (Log.isVerbose()) {
-                Log.verbose(e);
-            } else {
-                String msg1 = e.getMessage();
-                Log.error(msg1);
-                if (e.getCause() != null && e.getCause() != e) {
-                    String msg2 = e.getCause().getMessage();
-                    if (msg2 != null && !msg1.contains(msg2)) {
-                        Log.error(msg2);
-                    }
-                }
-            }
-            return false;
-        }
-    }
-
-    private void validateArguments() throws PackagerException {
-        String type = deployParams.getTargetFormat();
-        String ptype = (type != null) ? type : "default";
-        boolean imageOnly = deployParams.isTargetAppImage();
-        boolean hasAppImage = allOptions.contains(
-                CLIOptions.PREDEFINED_APP_IMAGE);
-        boolean hasRuntime = allOptions.contains(
-                CLIOptions.PREDEFINED_RUNTIME_IMAGE);
-        boolean installerOnly = !imageOnly && hasAppImage;
-        runtimeInstaller = !imageOnly && hasRuntime && !hasAppImage &&
-                !hasMainModule && !hasMainJar;
-
-        for (CLIOptions option : allOptions) {
-            if (!ValidOptions.checkIfSupported(option)) {
-                // includes option valid only on different platform
-                throw new PackagerException("ERR_UnsupportedOption",
-                        option.getIdWithPrefix());
-            }
-            if (imageOnly) {
-                if (!ValidOptions.checkIfImageSupported(option)) {
-                    throw new PackagerException("ERR_InvalidTypeOption",
-                        option.getIdWithPrefix(), type);
-                }
-            } else if (installerOnly || runtimeInstaller) {
-                if (!ValidOptions.checkIfInstallerSupported(option)) {
-                    if (runtimeInstaller) {
-                        throw new PackagerException("ERR_NoInstallerEntryPoint",
-                            option.getIdWithPrefix());
-                    } else {
-                        throw new PackagerException("ERR_InvalidTypeOption",
-                            option.getIdWithPrefix(), ptype);
-                   }
-                }
-            }
-        }
-        if (installerOnly && hasRuntime) {
-            // note --runtime-image is only for image or runtime installer.
-            throw new PackagerException("ERR_InvalidTypeOption",
-                    CLIOptions.PREDEFINED_RUNTIME_IMAGE.getIdWithPrefix(),
-                    ptype);
-        }
-        if (hasMainJar && hasMainModule) {
-            throw new PackagerException("ERR_BothMainJarAndModule");
-        }
-        if (imageOnly && !hasMainJar && !hasMainModule) {
-            throw new PackagerException("ERR_NoEntryPoint");
-        }
-    }
-
-    private jdk.jpackage.internal.Bundler getPlatformBundler() {
-        boolean appImage = deployParams.isTargetAppImage();
-        String type = deployParams.getTargetFormat();
-        String bundleType = (appImage ?  "IMAGE" : "INSTALLER");
-
-        for (jdk.jpackage.internal.Bundler bundler :
-                Bundlers.createBundlersInstance().getBundlers(bundleType)) {
-            if (type == null) {
-                 if (bundler.isDefault()
-                         && bundler.supported(runtimeInstaller)) {
-                     return bundler;
-                 }
-            } else {
-                 if ((appImage || type.equalsIgnoreCase(bundler.getID()))
-                         && bundler.supported(runtimeInstaller)) {
-                     return bundler;
-                 }
-            }
-        }
-        return null;
-    }
-
-    private void generateBundle(Map<String,? super Object> params)
-            throws PackagerException {
-
-        boolean bundleCreated = false;
-
-        // the temp dir needs to be fetched from the params early,
-        // to prevent each copy of the params (such as may be used for
-        // additional launchers) from generating a separate temp dir when
-        // the default is used (the default is a new temp directory)
-        // The bundler.cleanup() below would not otherwise be able to
-        // clean these extra (and unneeded) temp directories.
-        StandardBundlerParam.TEMP_ROOT.fetchFrom(params);
-
-        // determine what bundler to run
-        jdk.jpackage.internal.Bundler bundler = getPlatformBundler();
-
-        if (bundler == null) {
-            throw new PackagerException("ERR_InvalidInstallerType",
-                      deployParams.getTargetFormat());
-        }
-
-        Map<String, ? super Object> localParams = new HashMap<>(params);
-        try {
-            bundler.validate(localParams);
-            File result = bundler.execute(localParams, deployParams.outdir);
-            if (result == null) {
-                throw new PackagerException("MSG_BundlerFailed",
-                        bundler.getID(), bundler.getName());
-            }
-            Log.verbose(MessageFormat.format(
-                    I18N.getString("message.bundle-created"),
-                    bundler.getName()));
-        } catch (ConfigException e) {
-            Log.verbose(e);
-            if (e.getAdvice() != null)  {
-                throw new PackagerException(e, "MSG_BundlerConfigException",
-                        bundler.getName(), e.getMessage(), e.getAdvice());
-            } else {
-                throw new PackagerException(e,
-                       "MSG_BundlerConfigExceptionNoAdvice",
-                        bundler.getName(), e.getMessage());
-            }
-        } catch (RuntimeException re) {
-            Log.verbose(re);
-            throw new PackagerException(re, "MSG_BundlerRuntimeException",
-                    bundler.getName(), re.toString());
-        } finally {
-            if (userProvidedBuildRoot) {
-                Log.verbose(MessageFormat.format(
-                        I18N.getString("message.debug-working-directory"),
-                        (new File(buildRoot)).getAbsolutePath()));
-            } else {
-                // always clean up the temporary directory created
-                // when --temp option not used.
-                bundler.cleanup(localParams);
-            }
-        }
-    }
-
-    private void addResources(DeployParams deployParams,
-            String inputdir, String mainJar) throws PackagerException {
-
-        if (inputdir == null || inputdir.isEmpty()) {
-            return;
-        }
-
-        File baseDir = new File(inputdir);
-
-        if (!baseDir.isDirectory()) {
-            throw new PackagerException("ERR_InputNotDirectory", inputdir);
-        }
-        if (!baseDir.canRead()) {
-            throw new PackagerException("ERR_CannotReadInputDir", inputdir);
-        }
-
-        List<String> fileNames;
-        fileNames = new ArrayList<>();
-        try (Stream<Path> files = Files.list(baseDir.toPath())) {
-            files.forEach(file -> fileNames.add(
-                    file.getFileName().toString()));
-        } catch (IOException e) {
-            Log.error("Unable to add resources: " + e.getMessage());
-        }
-        fileNames.forEach(file -> deployParams.addResource(baseDir, file));
-
-        deployParams.setClasspath(mainJar);
-    }
-
-    static CLIOptions toCLIOption(String arg) {
-        CLIOptions option;
-        if ((option = argIds.get(arg)) == null) {
-            option = argShortIds.get(arg);
-        }
-        return option;
-    }
-
-    static Map<String, String> getPropertiesFromFile(String filename) {
-        Map<String, String> map = new HashMap<>();
-        // load properties file
-        File file = new File(filename);
-        Properties properties = new Properties();
-        try (FileInputStream in = new FileInputStream(file)) {
-            properties.load(in);
-        } catch (IOException e) {
-            Log.error("Exception: " + e.getMessage());
-        }
-
-        for (final String name: properties.stringPropertyNames()) {
-            map.put(name, properties.getProperty(name));
-        }
-
-        return map;
-    }
-
-    static List<String> getArgumentList(String inputString) {
-        List<String> list = new ArrayList<>();
-        if (inputString == null || inputString.isEmpty()) {
-             return list;
-        }
-
-        // The "pattern" regexp attempts to abide to the rule that
-        // strings are delimited by whitespace unless surrounded by
-        // quotes, then it is anything (including spaces) in the quotes.
-        Matcher m = pattern.matcher(inputString);
-        while (m.find()) {
-            String s = inputString.substring(m.start(), m.end()).trim();
-            // Ensure we do not have an empty string. trim() will take care of
-            // whitespace only strings. The regex preserves quotes and escaped
-            // chars so we need to clean them before adding to the List
-            if (!s.isEmpty()) {
-                list.add(unquoteIfNeeded(s));
-            }
-        }
-        return list;
-    }
-
-    private static String unquoteIfNeeded(String in) {
-        if (in == null) {
-            return null;
-        }
-
-        if (in.isEmpty()) {
-            return "";
-        }
-
-        // Use code points to preserve non-ASCII chars
-        StringBuilder sb = new StringBuilder();
-        int codeLen = in.codePointCount(0, in.length());
-        int quoteChar = -1;
-        for (int i = 0; i < codeLen; i++) {
-            int code = in.codePointAt(i);
-            if (code == '"' || code == '\'') {
-                // If quote is escaped make sure to copy it
-                if (i > 0 && in.codePointAt(i - 1) == '\\') {
-                    sb.deleteCharAt(sb.length() - 1);
-                    sb.appendCodePoint(code);
-                    continue;
-                }
-                if (quoteChar != -1) {
-                    if (code == quoteChar) {
-                        // close quote, skip char
-                        quoteChar = -1;
-                    } else {
-                        sb.appendCodePoint(code);
-                    }
-                } else {
-                    // opening quote, skip char
-                    quoteChar = code;
-                }
-            } else {
-                sb.appendCodePoint(code);
-            }
-        }
-        return sb.toString();
-    }
-
-    private String getMainClassFromManifest() {
-        if (mainJarPath == null ||
-            input == null ) {
-            return null;
-        }
-
-        JarFile jf;
-        try {
-            File file = new File(input, mainJarPath);
-            if (!file.exists()) {
-                return null;
-            }
-            jf = new JarFile(file);
-            Manifest m = jf.getManifest();
-            Attributes attrs = (m != null) ? m.getMainAttributes() : null;
-            if (attrs != null) {
-                return attrs.getValue(Attributes.Name.MAIN_CLASS);
-            }
-        } catch (IOException ignore) {}
-        return null;
-    }
-
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BasicBundlers.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.ServiceLoader;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * BasicBundlers
- *
- * A basic bundlers collection that loads the default bundlers.
- * Loads the common bundlers.
- * <UL>
- *     <LI>Windows file image</LI>
- *     <LI>Mac .app</LI>
- *     <LI>Linux file image</LI>
- *     <LI>Windows MSI</LI>
- *     <LI>Windows EXE</LI>
- *     <LI>Mac DMG</LI>
- *     <LI>Mac PKG</LI>
- *     <LI>Linux DEB</LI>
- *     <LI>Linux RPM</LI>
- *
- * </UL>
- */
-public class BasicBundlers implements Bundlers {
-
-    boolean defaultsLoaded = false;
-
-    private final Collection<Bundler> bundlers = new CopyOnWriteArrayList<>();
-
-    @Override
-    public Collection<Bundler> getBundlers() {
-        return Collections.unmodifiableCollection(bundlers);
-    }
-
-    @Override
-    public Collection<Bundler> getBundlers(String type) {
-        if (type == null) return Collections.emptySet();
-        switch (type) {
-            case "NONE":
-                return Collections.emptySet();
-            case "ALL":
-                return getBundlers();
-            default:
-                return Arrays.asList(getBundlers().stream()
-                        .filter(b -> type.equalsIgnoreCase(b.getBundleType()))
-                        .toArray(Bundler[]::new));
-        }
-    }
-
-    // Loads bundlers from the META-INF/services direct
-    @Override
-    public void loadBundlersFromServices(ClassLoader cl) {
-        ServiceLoader<Bundler> loader = ServiceLoader.load(Bundler.class, cl);
-        for (Bundler aLoader : loader) {
-            bundlers.add(aLoader);
-        }
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundleParams.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.File;
-import java.io.IOException;
-import java.util.*;
-import java.util.jar.Attributes;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-public class BundleParams {
-
-    final protected Map<String, ? super Object> params;
-
-    // RelativeFileSet
-    public static final String PARAM_APP_RESOURCES      = "appResources";
-
-    // String - Icon file name
-    public static final String PARAM_ICON               = "icon";
-
-    // String - Name of bundle file and native launcher
-    public static final String PARAM_NAME               = "name";
-
-    // String - application vendor, used by most of the bundlers
-    public static final String PARAM_VENDOR             = "vendor";
-
-    // String - email name and email, only used for debian */
-    public static final String PARAM_EMAIL              = "email";
-
-    // String - vendor <email>, only used for debian */
-    public static final String PARAM_MAINTAINER         = "maintainer";
-
-    /* String - Copyright. Used on Mac */
-    public static final String PARAM_COPYRIGHT          = "copyright";
-
-    // String - GUID on windows for MSI, CFBundleIdentifier on Mac
-    // If not compatible with requirements then bundler either do not bundle
-    // or autogenerate
-    public static final String PARAM_IDENTIFIER         = "identifier";
-
-    /* boolean - shortcut preferences */
-    public static final String PARAM_SHORTCUT           = "shortcutHint";
-    // boolean - menu shortcut preference
-    public static final String PARAM_MENU               = "menuHint";
-
-    // String - Application version. Format may differ for different bundlers
-    public static final String PARAM_VERSION            = "appVersion";
-
-    // String - Application release. Used on Linux.
-    public static final String PARAM_RELEASE            = "appRelease";
-
-    // String - Optional application description. Used by MSI and on Linux
-    public static final String PARAM_DESCRIPTION        = "description";
-
-    // String - License type. Needed on Linux (rpm)
-    public static final String PARAM_LICENSE_TYPE       = "licenseType";
-
-    // String - File with license. Format is OS/bundler specific
-    public static final String PARAM_LICENSE_FILE       = "licenseFile";
-
-    // String Main application class.
-    // Not used directly but used to derive default values
-    public static final String PARAM_APPLICATION_CLASS  = "applicationClass";
-
-    // boolean - Adds a dialog to let the user choose a directory
-    // where the product will be installed.
-    public static final String PARAM_INSTALLDIR_CHOOSER = "installdirChooser";
-
-    /**
-     * create a new bundle with all default values
-     */
-    public BundleParams() {
-        params = new HashMap<>();
-    }
-
-    /**
-     * Create a bundle params with a copy of the params
-     * @param params map of initial parameters to be copied in.
-     */
-    public BundleParams(Map<String, ?> params) {
-        this.params = new HashMap<>(params);
-    }
-
-    public void addAllBundleParams(Map<String, ? super Object> params) {
-        this.params.putAll(params);
-    }
-
-    // NOTE: we do not care about application parameters here
-    // as they will be embeded into jar file manifest and
-    // java launcher will take care of them!
-
-    public Map<String, ? super Object> getBundleParamsAsMap() {
-        return new HashMap<>(params);
-    }
-
-    public String getName() {
-        return APP_NAME.fetchFrom(params);
-    }
-
-    public void setAppResourcesList(
-            List<jdk.jpackage.internal.RelativeFileSet> rfs) {
-        putUnlessNull(APP_RESOURCES_LIST.getID(), rfs);
-    }
-
-    private void putUnlessNull(String param, Object value) {
-        if (value != null) {
-            params.put(param, value);
-        }
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Bundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.File;
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * Bundler
- *
- * The basic interface implemented by all Bundlers.
- */
-public interface Bundler {
-    /**
-     * @return User Friendly name of this bundler.
-     */
-    String getName();
-
-    /**
-     * @return Command line identifier of the bundler.  Should be unique.
-     */
-    String getID();
-
-    /**
-     * @return The bundle type of the bundle that is created by this bundler.
-     */
-    String getBundleType();
-
-    /**
-     * Determines if this bundler will execute with the given parameters.
-     *
-     * @param params The parameters to be validate.  Validation may modify
-     *               the map, so if you are going to be using the same map
-     *               across multiple bundlers you should pass in a deep copy.
-     * @return true if valid
-     * @throws ConfigException If the configuration params are incorrect.  The
-     *         exception may contain advice on how to modify the params map
-     *         to make it valid.
-     */
-    public boolean validate(Map<String, ? super Object> params)
-            throws ConfigException;
-
-    /**
-     * Creates a bundle from existing content.
-     *
-     * If a call to {@link #validate(java.util.Map)} date} returns true with
-     * the parameters map, then you can expect a valid output.
-     * However if an exception was thrown out of validate or it returned
-     * false then you should not expect sensible results from this call.
-     * It may or may not return a value, and it may or may not throw an
-     * exception.  But any output should not be considered valid or sane.
-     *
-     * @param params The Bundle parameters,
-     *               Keyed by the id from the ParamInfo.  Execution may
-     *               modify the map, so if you are going to be using the
-     *               same map across multiple bundlers you should pass
-     *               in a deep copy.
-     * @param outputParentDir
-     *   The parent dir that the returned bundle will be placed in.
-     * @return The resulting bundled file
-     *
-     * For a bundler that produces a single artifact file this will be the
-     * location of that artifact (.exe file, .deb file, etc)
-     *
-     * For a bundler that produces a specific directory format output this will
-     * be the location of that specific directory (.app file, etc).
-     *
-     * For a bundler that produce multiple files, this will be a parent
-     * directory of those files (linux and windows images), whose name is not
-     * relevant to the result.
-     *
-     * @throws java.lang.IllegalArgumentException for any of the following
-     * reasons:
-     *  <ul>
-     *      <li>A required parameter is not found in the params list, for
-     *      example missing the main class.</li>
-     *      <li>A parameter has the wrong type of an object, for example a
-     *      String where a File is required</li>
-     *      <li>Bundler specific incompatibilities with the parameters, for
-     *      example a bad version number format or an application id with
-     *      forward slashes.</li>
-     *  </ul>
-     */
-    public File execute(Map<String, ? super Object> params,
-            File outputParentDir) throws PackagerException;
-
-     /**
-     * Removes temporary files that are used for bundling.
-     */
-    public void cleanup(Map<String, ? super Object> params);
-
-    /**
-     * Returns "true" if this bundler is supported on current platform.
-     */
-    public boolean supported(boolean runtimeInstaller);
-
-    /**
-     * Returns "true" if this bundler is he default for the current platform.
-     */
-    public boolean isDefault();
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/BundlerParamInfo.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.Map;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-
-/**
- * BundlerParamInfo<T>
- *
- * A BundlerParamInfo encapsulates an individual bundler parameter of type <T>.
- */
-class BundlerParamInfo<T> {
-
-    /**
-     * The command line and hashmap name of the parameter
-     */
-    String id;
-
-    /**
-     * Type of the parameter
-     */
-    Class<T> valueType;
-
-    /**
-     * Indicates if value was set using default value function
-     */
-    boolean isDefaultValue;
-
-    /**
-     * If the value is not set, and no fallback value is found,
-     * the parameter uses the value returned by the producer.
-     */
-    Function<Map<String, ? super Object>, T> defaultValueFunction;
-
-    /**
-     * An optional string converter for command line arguments.
-     */
-    BiFunction<String, Map<String, ? super Object>, T> stringConverter;
-
-    String getID() {
-        return id;
-    }
-
-    Class<T> getValueType() {
-        return valueType;
-    }
-
-    boolean getIsDefaultValue() {
-        return isDefaultValue;
-    }
-
-    Function<Map<String, ? super Object>, T> getDefaultValueFunction() {
-        return defaultValueFunction;
-    }
-
-    BiFunction<String, Map<String, ? super Object>,T>
-            getStringConverter() {
-        return stringConverter;
-    }
-
-    @SuppressWarnings("unchecked")
-    final T fetchFrom(Map<String, ? super Object> params) {
-        return fetchFrom(params, true);
-    }
-
-    @SuppressWarnings("unchecked")
-    final T fetchFrom(Map<String, ? super Object> params,
-            boolean invokeDefault) {
-        Object o = params.get(getID());
-        if (o instanceof String && getStringConverter() != null) {
-            return getStringConverter().apply((String)o, params);
-        }
-
-        Class<T> klass = getValueType();
-        if (klass.isInstance(o)) {
-            return (T) o;
-        }
-        if (o != null) {
-            throw new IllegalArgumentException("Param " + getID()
-                    + " should be of type " + getValueType()
-                    + " but is a " + o.getClass());
-        }
-        if (params.containsKey(getID())) {
-            // explicit nulls are allowed
-            return null;
-        }
-
-        if (invokeDefault && (getDefaultValueFunction() != null)) {
-            T result =  getDefaultValueFunction().apply(params);
-            if (result != null) {
-                params.put(getID(), result);
-                isDefaultValue = true;
-            }
-            return result;
-        }
-
-        // ultimate fallback
-        return null;
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Bundlers.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.Collection;
-import java.util.Iterator;
-import java.util.ServiceLoader;
-
-/**
- * Bundlers
- *
- * The interface implemented by BasicBundlers
- */
-public interface Bundlers {
-
-    /**
-     * This convenience method will call
-     * {@link #createBundlersInstance(ClassLoader)}
-     * with the classloader that this Bundlers is loaded from.
-     *
-     * @return an instance of Bundlers loaded and configured from
-     *         the current ClassLoader.
-     */
-    public static Bundlers createBundlersInstance() {
-        return createBundlersInstance(Bundlers.class.getClassLoader());
-    }
-
-    /**
-     * This convenience method will automatically load a Bundlers instance
-     * from either META-INF/services or the default
-     * {@link BasicBundlers} if none are found in
-     * the services meta-inf.
-     *
-     * After instantiating the bundlers instance it will load the default
-     * bundlers via {@link #loadDefaultBundlers()} as well as requesting
-     * the services loader to load any other bundelrs via
-     * {@link #loadBundlersFromServices(ClassLoader)}.
-
-     *
-     * @param servicesClassLoader the classloader to search for
-     *                            META-INF/service registered bundlers
-     * @return an instance of Bundlers loaded and configured from
-     *         the specified ClassLoader
-     */
-    public static Bundlers createBundlersInstance(
-            ClassLoader servicesClassLoader) {
-        ServiceLoader<Bundlers> bundlersLoader =
-                ServiceLoader.load(Bundlers.class, servicesClassLoader);
-        Bundlers bundlers = null;
-        Iterator<Bundlers> iter = bundlersLoader.iterator();
-        if (iter.hasNext()) {
-            bundlers = iter.next();
-        }
-        if (bundlers == null) {
-            bundlers = new BasicBundlers();
-        }
-
-        bundlers.loadBundlersFromServices(servicesClassLoader);
-        return bundlers;
-    }
-
-    /**
-     * Returns all of the preconfigured, requested, and manually
-     * configured bundlers loaded with this instance.
-     *
-     * @return  a read-only collection of the requested bundlers
-     */
-    Collection<Bundler> getBundlers();
-
-    /**
-     * Returns all of the preconfigured, requested, and manually
-     * configured bundlers loaded with this instance that are of
-     * a specific BundleType, such as disk images, installers, or
-     * remote installers.
-     *
-     * @return a read-only collection of the requested bundlers
-     */
-    Collection<Bundler> getBundlers(String type);
-
-    /**
-     * Loads bundlers from the META-INF/services directly.
-     *
-     * This method is called from the
-     * {@link #createBundlersInstance(ClassLoader)}
-     * and {@link #createBundlersInstance()} methods.
-     */
-    void loadBundlersFromServices(ClassLoader cl);
-
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/CLIHelp.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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.ResourceBundle;
-import java.io.File;
-import java.text.MessageFormat;
-
-
-/**
- * CLIHelp
- *
- * Generate and show the command line interface help message(s).
- */
-public class CLIHelp {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.HelpResources");
-
-    // generates --help for jpackage's CLI
-    public static void showHelp(boolean noArgs) {
-
-        if (noArgs) {
-            Log.info(I18N.getString("MSG_Help_no_args"));
-        } else {
-            Platform platform = (Log.isVerbose()) ?
-                    Platform.UNKNOWN : Platform.getPlatform();
-            String types;
-            String pLaunchOptions;
-            String pInstallOptions;
-            String pInstallDir;
-            switch (platform) {
-                case MAC:
-                    types = "{\"app-image\", \"dmg\", \"pkg\"}";
-                    pLaunchOptions = I18N.getString("MSG_Help_mac_launcher");
-                    pInstallOptions = "";
-                    pInstallDir
-                            = I18N.getString("MSG_Help_mac_linux_install_dir");
-                    break;
-                case LINUX:
-                    types = "{\"app-image\", \"rpm\", \"deb\"}";
-                    pLaunchOptions = "";
-                    pInstallOptions = I18N.getString("MSG_Help_linux_install");
-                    pInstallDir
-                            = I18N.getString("MSG_Help_mac_linux_install_dir");
-                    break;
-                case WINDOWS:
-                    types = "{\"app-image\", \"exe\", \"msi\"}";
-                    pLaunchOptions = I18N.getString("MSG_Help_win_launcher");
-                    pInstallOptions = I18N.getString("MSG_Help_win_install");
-                    pInstallDir
-                            = I18N.getString("MSG_Help_win_install_dir");
-                    break;
-                default:
-                    types = "{\"app-image\", \"exe\", \"msi\", \"rpm\", \"deb\", \"pkg\", \"dmg\"}";
-                    pLaunchOptions = I18N.getString("MSG_Help_win_launcher")
-                            + I18N.getString("MSG_Help_mac_launcher");
-                    pInstallOptions = I18N.getString("MSG_Help_win_install")
-                            + I18N.getString("MSG_Help_linux_install");
-                    pInstallDir
-                            = I18N.getString("MSG_Help_default_install_dir");
-                    break;
-            }
-            Log.info(MessageFormat.format(I18N.getString("MSG_Help"),
-                    File.pathSeparator, types, pLaunchOptions,
-                    pInstallOptions, pInstallDir));
-        }
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ConfigException.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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;
-
-public class ConfigException extends Exception {
-    private static final long serialVersionUID = 1L;
-    final String advice;
-
-    public ConfigException(String msg, String advice) {
-        super(msg);
-        this.advice = advice;
-    }
-
-    public ConfigException(String msg, String advice, Exception cause) {
-        super(msg, cause);
-        this.advice = advice;
-    }
-
-    public ConfigException(Exception cause) {
-        super(cause);
-        this.advice = null;
-    }
-
-    public String getAdvice() {
-        return advice;
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/DeployParams.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,354 +0,0 @@
-/*
- * Copyright (c) 2011, 2019, 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.File;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.InvalidPathException;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-/**
- * DeployParams
- *
- * This class is generated and used in Arguments.processArguments() as
- * intermediate step in generating the BundleParams and ultimately the Bundles
- */
-public class DeployParams {
-
-    final List<RelativeFileSet> resources = new ArrayList<>();
-
-    String targetFormat = null; // means default type for this platform
-
-    File outdir = null;
-
-    // raw arguments to the bundler
-    Map<String, ? super Object> bundlerArguments = new LinkedHashMap<>();
-
-    public void setOutput(File output) {
-        outdir = output;
-    }
-
-    static class Template {
-        File in;
-        File out;
-
-        Template(File in, File out) {
-            this.in = in;
-            this.out = out;
-        }
-    }
-
-    // we need to expand as in some cases
-    // (most notably jpackage)
-    // we may get "." as filename and assumption is we include
-    // everything in the given folder
-    // (IOUtils.copyfiles() have recursive behavior)
-    List<File> expandFileset(File root) {
-        List<File> files = new LinkedList<>();
-        if (!Files.isSymbolicLink(root.toPath())) {
-            if (root.isDirectory()) {
-                File[] children = root.listFiles();
-                if (children != null) {
-                    for (File f : children) {
-                        files.addAll(expandFileset(f));
-                    }
-                }
-            } else {
-                files.add(root);
-            }
-        }
-        return files;
-    }
-
-    public void addResource(File baseDir, String path) {
-        addResource(baseDir, new File(baseDir, path));
-    }
-
-    public void addResource(File baseDir, File file) {
-        // normalize initial file
-        // to strip things like "." in the path
-        // or it can confuse symlink detection logic
-        file = file.getAbsoluteFile();
-
-        if (baseDir == null) {
-            baseDir = file.getParentFile();
-        }
-        resources.add(new RelativeFileSet(
-                baseDir, new LinkedHashSet<>(expandFileset(file))));
-    }
-
-    void setClasspath(String mainJarPath) {
-        String classpath;
-        // we want main jar first on the classpath
-        if (mainJarPath != null) {
-            classpath = mainJarPath + File.pathSeparator;
-        } else {
-            classpath = "";
-        }
-        for (RelativeFileSet resource : resources) {
-             for (String file : resource.getIncludedFiles()) {
-                 if (file.endsWith(".jar")) {
-                     if (!file.equals(mainJarPath)) {
-                         classpath += file + File.pathSeparator;
-                     }
-                 }
-             }
-        }
-        addBundleArgument(
-                StandardBundlerParam.CLASSPATH.getID(), classpath);
-    }
-
-    static void validateName(String s, boolean forApp)
-            throws PackagerException {
-
-        String exceptionKey = forApp ?
-            "ERR_InvalidAppName" : "ERR_InvalidSLName";
-
-        if (s == null) {
-            if (forApp) {
-                return;
-            } else {
-                throw new PackagerException(exceptionKey, s);
-            }
-        }
-        if (s.length() == 0 || s.charAt(s.length() - 1) == '\\') {
-            throw new PackagerException(exceptionKey, s);
-        }
-        try {
-            // name must be valid path element for this file system
-            Path p = (new File(s)).toPath();
-            // and it must be a single name element in a path
-            if (p.getNameCount() != 1) {
-                throw new PackagerException(exceptionKey, s);
-            }
-        } catch (InvalidPathException ipe) {
-            throw new PackagerException(ipe, exceptionKey, s);
-        }
-
-        for (int i = 0; i < s.length(); i++) {
-            char a = s.charAt(i);
-            // We check for ASCII codes first which we accept. If check fails,
-            // check if it is acceptable extended ASCII or unicode character.
-            if (a < ' ' || a > '~') {
-                // Accept anything else including special chars like copyright
-                // symbols. Note: space will be included by ASCII check above,
-                // but other whitespace like tabs or new line will be rejected.
-                if (Character.isISOControl(a)  ||
-                        Character.isWhitespace(a)) {
-                    throw new PackagerException(exceptionKey, s);
-                }
-            } else if (a == '"' || a == '%') {
-                throw new PackagerException(exceptionKey, s);
-            }
-        }
-    }
-
-    public void validate() throws PackagerException {
-        boolean hasModule = (bundlerArguments.get(
-                Arguments.CLIOptions.MODULE.getId()) != null);
-        boolean hasAppImage = (bundlerArguments.get(
-                Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId()) != null);
-        boolean hasClass = (bundlerArguments.get(
-                Arguments.CLIOptions.APPCLASS.getId()) != null);
-        boolean hasMain = (bundlerArguments.get(
-                Arguments.CLIOptions.MAIN_JAR.getId()) != null);
-        boolean hasRuntimeImage = (bundlerArguments.get(
-                Arguments.CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId()) != null);
-        boolean hasInput = (bundlerArguments.get(
-                Arguments.CLIOptions.INPUT.getId()) != null);
-        boolean hasModulePath = (bundlerArguments.get(
-                Arguments.CLIOptions.MODULE_PATH.getId()) != null);
-        boolean runtimeInstaller = !isTargetAppImage() &&
-                !hasAppImage && !hasModule && !hasMain && hasRuntimeImage;
-
-        if (isTargetAppImage()) {
-            // Module application requires --runtime-image or --module-path
-            if (hasModule) {
-                if (!hasModulePath && !hasRuntimeImage) {
-                    throw new PackagerException("ERR_MissingArgument",
-                            "--runtime-image or --module-path");
-                }
-            } else {
-                if (!hasInput) {
-                    throw new PackagerException(
-                           "ERR_MissingArgument", "--input");
-                }
-            }
-        } else {
-            if (!runtimeInstaller) {
-                if (hasModule) {
-                    if (!hasModulePath && !hasRuntimeImage && !hasAppImage) {
-                        throw new PackagerException("ERR_MissingArgument",
-                            "--runtime-image, --module-path or --app-image");
-                    }
-                } else {
-                    if (!hasInput && !hasAppImage) {
-                        throw new PackagerException("ERR_MissingArgument",
-                                "--input or --app-image");
-                    }
-                }
-            }
-        }
-
-        // if bundling non-modular image, or installer without app-image
-        // then we need some resources and a main class
-        if (!hasModule && !hasAppImage && !runtimeInstaller) {
-            if (resources.isEmpty()) {
-                throw new PackagerException("ERR_MissingAppResources");
-            }
-            if (!hasMain) {
-                throw new PackagerException("ERR_MissingArgument",
-                        "--main-jar");
-            }
-        }
-
-        String name = (String)bundlerArguments.get(
-                Arguments.CLIOptions.NAME.getId());
-        validateName(name, true);
-
-        // Validate app image if set
-        String appImage = (String)bundlerArguments.get(
-                Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId());
-        if (appImage != null) {
-            File appImageDir = new File(appImage);
-            if (!appImageDir.exists() || appImageDir.list().length == 0) {
-                throw new PackagerException("ERR_AppImageNotExist", appImage);
-            }
-        }
-
-        // Validate temp dir
-        String root = (String)bundlerArguments.get(
-                Arguments.CLIOptions.TEMP_ROOT.getId());
-        if (root != null) {
-            String [] contents = (new File(root)).list();
-
-            if (contents != null && contents.length > 0) {
-                throw new PackagerException("ERR_BuildRootInvalid", root);
-            }
-        }
-
-        // Validate license file if set
-        String license = (String)bundlerArguments.get(
-                Arguments.CLIOptions.LICENSE_FILE.getId());
-        if (license != null) {
-            File licenseFile = new File(license);
-            if (!licenseFile.exists()) {
-                throw new PackagerException("ERR_LicenseFileNotExit");
-            }
-        }
-    }
-
-    void setTargetFormat(String t) {
-        targetFormat = t;
-    }
-
-    String getTargetFormat() {
-        return targetFormat;
-    }
-
-    boolean isTargetAppImage() {
-        return ("app-image".equals(targetFormat));
-    }
-
-    private static final Set<String> multi_args = new TreeSet<>(Arrays.asList(
-            StandardBundlerParam.JAVA_OPTIONS.getID(),
-            StandardBundlerParam.ARGUMENTS.getID(),
-            StandardBundlerParam.MODULE_PATH.getID(),
-            StandardBundlerParam.ADD_MODULES.getID(),
-            StandardBundlerParam.LIMIT_MODULES.getID(),
-            StandardBundlerParam.FILE_ASSOCIATIONS.getID()
-    ));
-
-    @SuppressWarnings("unchecked")
-    public void addBundleArgument(String key, Object value) {
-        // special hack for multi-line arguments
-        if (multi_args.contains(key)) {
-            Object existingValue = bundlerArguments.get(key);
-            if (existingValue instanceof String && value instanceof String) {
-                String delim = "\n\n";
-                if (key.equals(StandardBundlerParam.MODULE_PATH.getID())) {
-                    delim = File.pathSeparator;
-                } else if (key.equals(
-                        StandardBundlerParam.ADD_MODULES.getID())) {
-                    delim = ",";
-                }
-                bundlerArguments.put(key, existingValue + delim + value);
-            } else if (existingValue instanceof List && value instanceof List) {
-                ((List)existingValue).addAll((List)value);
-            } else if (existingValue instanceof Map &&
-                value instanceof String && ((String)value).contains("=")) {
-                String[] mapValues = ((String)value).split("=", 2);
-                ((Map)existingValue).put(mapValues[0], mapValues[1]);
-            } else {
-                bundlerArguments.put(key, value);
-            }
-        } else {
-            bundlerArguments.put(key, value);
-        }
-    }
-
-    BundleParams getBundleParams() {
-        BundleParams bundleParams = new BundleParams();
-
-        // construct app resources relative to destination folder!
-        bundleParams.setAppResourcesList(resources);
-
-        Map<String, String> unescapedHtmlParams = new TreeMap<>();
-        Map<String, String> escapedHtmlParams = new TreeMap<>();
-
-        // check for collisions
-        TreeSet<String> keys = new TreeSet<>(bundlerArguments.keySet());
-        keys.retainAll(bundleParams.getBundleParamsAsMap().keySet());
-
-        if (!keys.isEmpty()) {
-            throw new RuntimeException("Deploy Params and Bundler Arguments "
-                    + "overlap in the following values:" + keys.toString());
-        }
-
-        bundleParams.addAllBundleParams(bundlerArguments);
-
-        return bundleParams;
-    }
-
-    @Override
-    public String toString() {
-        return "DeployParams {" + "output: " + outdir
-                + " resources: {" + resources + "}}";
-    }
-
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/DottedVersion.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2019, 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.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.regex.Pattern;
-
-/**
- * Dotted numeric version string.
- * E.g.: 1.0.37, 10, 0.5
- */
-class DottedVersion implements Comparable<String> {
-
-    public DottedVersion(String version) {
-        greedy = true;
-        components = parseVersionString(version, greedy);
-        value = version;
-    }
-
-    private DottedVersion(String version, boolean greedy) {
-        this.greedy = greedy;
-        components = parseVersionString(version, greedy);
-        value = version;
-    }
-
-    public static DottedVersion greedy(String version) {
-        return new DottedVersion(version);
-    }
-
-    public static DottedVersion lazy(String version) {
-        return new DottedVersion(version, false);
-    }
-
-    @Override
-    public int compareTo(String o) {
-        int result = 0;
-        int[] otherComponents = parseVersionString(o, greedy);
-        for (int i = 0; i < Math.min(components.length, otherComponents.length)
-                && result == 0; ++i) {
-            result = components[i] - otherComponents[i];
-        }
-
-        if (result == 0) {
-            result = components.length - otherComponents.length;
-        }
-
-        return result;
-    }
-
-    private static int[] parseVersionString(String version, boolean greedy) {
-        Objects.requireNonNull(version);
-        if (version.isEmpty()) {
-            if (!greedy) {
-                return new int[] {0};
-            }
-            throw new IllegalArgumentException("Version may not be empty string");
-        }
-
-        int lastNotZeroIdx = -1;
-        List<Integer> components = new ArrayList<>();
-        for (var component : version.split("\\.", -1)) {
-            if (component.isEmpty()) {
-                if (!greedy) {
-                    break;
-                }
-
-                throw new IllegalArgumentException(String.format(
-                        "Version [%s] contains a zero lenght component", version));
-            }
-
-            if (!DIGITS.matcher(component).matches()) {
-                // Catch "+N" and "-N"  cases.
-                if (!greedy) {
-                    break;
-                }
-
-                throw new IllegalArgumentException(String.format(
-                        "Version [%s] contains invalid component [%s]", version,
-                        component));
-            }
-
-            final int num;
-            try {
-                num = Integer.parseInt(component);
-            } catch (NumberFormatException ex) {
-                if (!greedy) {
-                    break;
-                }
-
-                throw ex;
-            }
-
-            if (num != 0) {
-                lastNotZeroIdx = components.size();
-            }
-            components.add(num);
-        }
-
-        if (lastNotZeroIdx + 1 != components.size()) {
-            // Strip trailing zeros.
-            components = components.subList(0, lastNotZeroIdx + 1);
-        }
-
-        if (components.isEmpty()) {
-            components.add(0);
-        }
-        return components.stream().mapToInt(Integer::intValue).toArray();
-    }
-
-    @Override
-    public String toString() {
-        return value;
-    }
-
-    final private int[] components;
-    final private String value;
-    final private boolean greedy;
-
-    private static final Pattern DIGITS = Pattern.compile("\\d+");
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Executor.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * Copyright (c) 2019, 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.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-final public class Executor {
-
-    Executor() {
-    }
-
-    Executor setOutputConsumer(Consumer<Stream<String>> v) {
-        outputConsumer = v;
-        return this;
-    }
-
-    Executor saveOutput(boolean v) {
-        saveOutput = v;
-        return this;
-    }
-
-    Executor setProcessBuilder(ProcessBuilder v) {
-        pb = v;
-        return this;
-    }
-
-    Executor setCommandLine(String... cmdline) {
-        return setProcessBuilder(new ProcessBuilder(cmdline));
-    }
-
-    List<String> getOutput() {
-        return output;
-    }
-
-    Executor executeExpectSuccess() throws IOException {
-        int ret = execute();
-        if (0 != ret) {
-            throw new IOException(
-                    String.format("Command %s exited with %d code",
-                            createLogMessage(pb), ret));
-        }
-        return this;
-    }
-
-    int execute() throws IOException {
-        output = null;
-
-        boolean needProcessOutput = outputConsumer != null || Log.isVerbose() || saveOutput;
-        if (needProcessOutput) {
-            pb.redirectErrorStream(true);
-        } else {
-            // We are not going to read process output, so need to notify
-            // ProcessBuilder about this. Otherwise some processes might just
-            // hang up (`ldconfig -p`).
-            pb.redirectError(ProcessBuilder.Redirect.DISCARD);
-            pb.redirectOutput(ProcessBuilder.Redirect.DISCARD);
-        }
-
-        Log.verbose(String.format("Running %s", createLogMessage(pb)));
-        Process p = pb.start();
-
-        if (needProcessOutput) {
-            try (var br = new BufferedReader(new InputStreamReader(
-                    p.getInputStream()))) {
-                final List<String> savedOutput;
-                // Need to save output if explicitely requested (saveOutput=true) or
-                // if will be used used by multiple consumers
-                if ((outputConsumer != null && Log.isVerbose()) || saveOutput) {
-                    savedOutput = br.lines().collect(Collectors.toList());
-                    if (saveOutput) {
-                        output = savedOutput;
-                    }
-                } else {
-                    savedOutput = null;
-                }
-
-                Supplier<Stream<String>> outputStream = () -> {
-                    if (savedOutput != null) {
-                        return savedOutput.stream();
-                    }
-                    return br.lines();
-                };
-
-                if (Log.isVerbose()) {
-                    outputStream.get().forEach(Log::verbose);
-                }
-
-                if (outputConsumer != null) {
-                    outputConsumer.accept(outputStream.get());
-                }
-
-                if (savedOutput == null) {
-                    // For some processes on Linux if the output stream
-                    // of the process is opened but not consumed, the process
-                    // would exit with code 141.
-                    // It turned out that reading just a single line of process
-                    // output fixes the problem, but let's process
-                    // all of the output, just in case.
-                    br.lines().forEach(x -> {});
-                }
-            }
-        }
-
-        try {
-            return p.waitFor();
-        } catch (InterruptedException ex) {
-            Log.verbose(ex);
-            throw new RuntimeException(ex);
-        }
-    }
-
-    static Executor of(String... cmdline) {
-        return new Executor().setCommandLine(cmdline);
-    }
-
-    static Executor of(ProcessBuilder pb) {
-        return new Executor().setProcessBuilder(pb);
-    }
-
-    private static String createLogMessage(ProcessBuilder pb) {
-        StringBuilder sb = new StringBuilder();
-        sb.append(String.format("%s", pb.command()));
-        if (pb.directory() != null) {
-            sb.append(String.format("in %s", pb.directory().getAbsolutePath()));
-        }
-        return sb.toString();
-    }
-
-    private ProcessBuilder pb;
-    private boolean saveOutput;
-    private List<String> output;
-    private Consumer<Stream<String>> outputConsumer;
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FileAssociation.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2019, 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.File;
-import java.nio.file.Path;
-import java.util.*;
-import java.util.stream.Collectors;
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-final class FileAssociation {
-    void verify() {
-        if (extensions.isEmpty()) {
-            Log.error(I18N.getString(
-                    "message.creating-association-with-null-extension"));
-        }
-    }
-
-    static List<FileAssociation> fetchFrom(Map<String, ? super Object> params) {
-        String launcherName = APP_NAME.fetchFrom(params);
-
-        return FILE_ASSOCIATIONS.fetchFrom(params).stream().filter(
-                Objects::nonNull).map(fa -> {
-                    FileAssociation assoc = new FileAssociation();
-
-                    assoc.launcherPath = Path.of(launcherName);
-                    assoc.description = FA_DESCRIPTION.fetchFrom(fa);
-                    assoc.extensions = Optional.ofNullable(
-                            FA_EXTENSIONS.fetchFrom(fa)).orElse(Collections.emptyList());
-                    assoc.mimeTypes = Optional.ofNullable(
-                            FA_CONTENT_TYPE.fetchFrom(fa)).orElse(Collections.emptyList());
-
-                    File icon = FA_ICON.fetchFrom(fa);
-                    if (icon != null) {
-                        assoc.iconPath = icon.toPath();
-                    }
-
-                    return assoc;
-                }).collect(Collectors.toList());
-    }
-
-    Path launcherPath;
-    Path iconPath;
-    List<String> mimeTypes;
-    List<String> extensions;
-    String description;
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/I18N.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2019, 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.ResourceBundle;
-
-class I18N {
-
-    static String getString(String key) {
-        if (PLATFORM.containsKey(key)) {
-            return PLATFORM.getString(key);
-        }
-        return SHARED.getString(key);
-    }
-
-    private static final ResourceBundle SHARED = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MainResources");
-
-    private static final ResourceBundle PLATFORM;
-
-    static {
-        if (Platform.isLinux()) {
-            PLATFORM = ResourceBundle.getBundle(
-                    "jdk.jpackage.internal.resources.LinuxResources");
-        } else if (Platform.isWindows()) {
-            PLATFORM = ResourceBundle.getBundle(
-                    "jdk.jpackage.internal.resources.WinResources");
-        } else if (Platform.isMac()) {
-            PLATFORM = ResourceBundle.getBundle(
-                    "jdk.jpackage.internal.resources.MacResources");
-        } else {
-            throw new IllegalStateException("Unknwon platform");
-        }
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,335 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.*;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.nio.channels.FileChannel;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-
-/**
- * IOUtils
- *
- * A collection of static utility methods.
- */
-public class IOUtils {
-
-    public static void deleteRecursive(File path) throws IOException {
-        if (!path.exists()) {
-            return;
-        }
-        Path directory = path.toPath();
-        Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
-            @Override
-            public FileVisitResult visitFile(Path file,
-                            BasicFileAttributes attr) throws IOException {
-                if (Platform.getPlatform() == Platform.WINDOWS) {
-                    Files.setAttribute(file, "dos:readonly", false);
-                }
-                Files.delete(file);
-                return FileVisitResult.CONTINUE;
-            }
-
-            @Override
-            public FileVisitResult preVisitDirectory(Path dir,
-                            BasicFileAttributes attr) throws IOException {
-                if (Platform.getPlatform() == Platform.WINDOWS) {
-                    Files.setAttribute(dir, "dos:readonly", false);
-                }
-                return FileVisitResult.CONTINUE;
-            }
-
-            @Override
-            public FileVisitResult postVisitDirectory(Path dir, IOException e)
-                            throws IOException {
-                Files.delete(dir);
-                return FileVisitResult.CONTINUE;
-            }
-        });
-    }
-
-    public static void copyRecursive(Path src, Path dest) throws IOException {
-        copyRecursive(src, dest, List.of());
-    }
-
-    public static void copyRecursive(Path src, Path dest,
-            final List<String> excludes) throws IOException {
-        Files.walkFileTree(src, new SimpleFileVisitor<Path>() {
-            @Override
-            public FileVisitResult preVisitDirectory(final Path dir,
-                    final BasicFileAttributes attrs) throws IOException {
-                if (excludes.contains(dir.toFile().getName())) {
-                    return FileVisitResult.SKIP_SUBTREE;
-                } else {
-                    Files.createDirectories(dest.resolve(src.relativize(dir)));
-                    return FileVisitResult.CONTINUE;
-                }
-            }
-
-            @Override
-            public FileVisitResult visitFile(final Path file,
-                    final BasicFileAttributes attrs) throws IOException {
-                if (!excludes.contains(file.toFile().getName())) {
-                    Files.copy(file, dest.resolve(src.relativize(file)));
-                }
-                return FileVisitResult.CONTINUE;
-            }
-        });
-    }
-
-    public static void copyFile(File sourceFile, File destFile)
-            throws IOException {
-        destFile.getParentFile().mkdirs();
-
-        //recreate the file as existing copy may have weird permissions
-        destFile.delete();
-        destFile.createNewFile();
-
-        try (FileChannel source = new FileInputStream(sourceFile).getChannel();
-            FileChannel destination =
-                    new FileOutputStream(destFile).getChannel()) {
-
-            if (destination != null && source != null) {
-                destination.transferFrom(source, 0, source.size());
-            }
-        }
-
-        //preserve executable bit!
-        if (sourceFile.canExecute()) {
-            destFile.setExecutable(true, false);
-        }
-        if (!sourceFile.canWrite()) {
-            destFile.setReadOnly();
-        }
-        destFile.setReadable(true, false);
-    }
-
-    // run "launcher paramfile" in the directory where paramfile is kept
-    public static void run(String launcher, File paramFile)
-            throws IOException {
-        if (paramFile != null && paramFile.exists()) {
-            ProcessBuilder pb =
-                    new ProcessBuilder(launcher, paramFile.getName());
-            pb = pb.directory(paramFile.getParentFile());
-            exec(pb);
-        }
-    }
-
-    public static void exec(ProcessBuilder pb)
-            throws IOException {
-        exec(pb, false, null);
-    }
-
-    static void exec(ProcessBuilder pb, boolean testForPresenseOnly,
-            PrintStream consumer) throws IOException {
-        List<String> output = new ArrayList<>();
-        Executor exec = Executor.of(pb).setOutputConsumer(lines -> {
-            lines.forEach(output::add);
-            if (consumer != null) {
-                output.forEach(consumer::println);
-            }
-        });
-
-        if (testForPresenseOnly) {
-            exec.execute();
-        } else {
-            exec.executeExpectSuccess();
-        }
-    }
-
-    public static int getProcessOutput(List<String> result, String... args)
-            throws IOException, InterruptedException {
-
-        ProcessBuilder pb = new ProcessBuilder(args);
-
-        final Process p = pb.start();
-
-        List<String> list = new ArrayList<>();
-
-        final BufferedReader in =
-                new BufferedReader(new InputStreamReader(p.getInputStream()));
-        final BufferedReader err =
-                new BufferedReader(new InputStreamReader(p.getErrorStream()));
-
-        Thread t = new Thread(() -> {
-            try {
-                String line;
-                while ((line = in.readLine()) != null) {
-                    list.add(line);
-                }
-            } catch (IOException ioe) {
-                Log.verbose(ioe);
-            }
-
-            try {
-                String line;
-                while ((line = err.readLine()) != null) {
-                    Log.error(line);
-                }
-            } catch (IOException ioe) {
-                  Log.verbose(ioe);
-            }
-        });
-        t.setDaemon(true);
-        t.start();
-
-        int ret = p.waitFor();
-
-        result.clear();
-        result.addAll(list);
-
-        return ret;
-    }
-
-    static void writableOutputDir(Path outdir) throws PackagerException {
-        File file = outdir.toFile();
-
-        if (!file.isDirectory() && !file.mkdirs()) {
-            throw new PackagerException("error.cannot-create-output-dir",
-                    file.getAbsolutePath());
-        }
-        if (!file.canWrite()) {
-            throw new PackagerException("error.cannot-write-to-output-dir",
-                    file.getAbsolutePath());
-        }
-    }
-
-    public static Path replaceSuffix(Path path, String suffix) {
-        Path parent = path.getParent();
-        String filename = path.getFileName().toString().replaceAll("\\.[^.]*$", "")
-                + Optional.ofNullable(suffix).orElse("");
-        return parent != null ? parent.resolve(filename) : Path.of(filename);
-    }
-
-    public static Path addSuffix(Path path, String suffix) {
-        Path parent = path.getParent();
-        String filename = path.getFileName().toString() + suffix;
-        return parent != null ? parent.resolve(filename) : Path.of(filename);
-    }
-
-    public static String getSuffix(Path path) {
-        String filename = replaceSuffix(path.getFileName(), null).toString();
-        return path.getFileName().toString().substring(filename.length());
-    }
-
-    @FunctionalInterface
-    public static interface XmlConsumer {
-        void accept(XMLStreamWriter xml) throws IOException, XMLStreamException;
-    }
-
-    public static void createXml(Path dstFile, XmlConsumer xmlConsumer) throws
-            IOException {
-        XMLOutputFactory xmlFactory = XMLOutputFactory.newInstance();
-        try (Writer w = Files.newBufferedWriter(dstFile)) {
-            // Wrap with pretty print proxy
-            XMLStreamWriter xml = (XMLStreamWriter) Proxy.newProxyInstance(
-                    XMLStreamWriter.class.getClassLoader(), new Class<?>[]{
-                XMLStreamWriter.class}, new PrettyPrintHandler(
-                    xmlFactory.createXMLStreamWriter(w)));
-
-            xml.writeStartDocument();
-            xmlConsumer.accept(xml);
-            xml.writeEndDocument();
-            xml.flush();
-            xml.close();
-        } catch (XMLStreamException ex) {
-            throw new IOException(ex);
-        } catch (IOException ex) {
-            throw ex;
-        }
-    }
-
-    private static class PrettyPrintHandler implements InvocationHandler {
-
-        PrettyPrintHandler(XMLStreamWriter target) {
-            this.target = target;
-        }
-
-        @Override
-        public Object invoke(Object proxy, Method method, Object[] args) throws
-                Throwable {
-            switch (method.getName()) {
-                case "writeStartElement":
-                    // update state of parent node
-                    if (depth > 0) {
-                        hasChildElement.put(depth - 1, true);
-                    }
-                    // reset state of current node
-                    hasChildElement.put(depth, false);
-                    // indent for current depth
-                    target.writeCharacters(EOL);
-                    target.writeCharacters(repeat(depth, INDENT));
-                    depth++;
-                    break;
-                case "writeEndElement":
-                    depth--;
-                    if (hasChildElement.get(depth) == true) {
-                        target.writeCharacters(EOL);
-                        target.writeCharacters(repeat(depth, INDENT));
-                    }
-                    break;
-                case "writeProcessingInstruction":
-                case "writeEmptyElement":
-                    // update state of parent node
-                    if (depth > 0) {
-                        hasChildElement.put(depth - 1, true);
-                    }
-                    // indent for current depth
-                    target.writeCharacters(EOL);
-                    target.writeCharacters(repeat(depth, INDENT));
-                    break;
-                default:
-                    break;
-            }
-            method.invoke(target, args);
-            return null;
-        }
-
-        private static String repeat(int d, String s) {
-            StringBuilder sb = new StringBuilder();
-            while (d-- > 0) {
-                sb.append(s);
-            }
-            return sb.toString();
-        }
-
-        private final XMLStreamWriter target;
-        private int depth = 0;
-        private final Map<Integer, Boolean> hasChildElement = new HashMap<>();
-        private static final String INDENT = "  ";
-        private static final String EOL = "\n";
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkBundlerHelper.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,397 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.File;
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.ResourceBundle;
-import java.util.Set;
-import java.util.Optional;
-import java.util.Arrays;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.regex.Matcher;
-import java.util.spi.ToolProvider;
-import java.util.jar.JarFile;
-import java.lang.module.Configuration;
-import java.lang.module.ResolvedModule;
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleFinder;
-import java.lang.module.ModuleReference;
-import jdk.internal.module.ModulePath;
-
-final class JLinkBundlerHelper {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MainResources");
-
-    static final ToolProvider JLINK_TOOL =
-            ToolProvider.findFirst("jlink").orElseThrow();
-
-    static File getMainJar(Map<String, ? super Object> params) {
-        File result = null;
-        RelativeFileSet fileset =
-                StandardBundlerParam.MAIN_JAR.fetchFrom(params);
-
-        if (fileset != null) {
-            String filename = fileset.getIncludedFiles().iterator().next();
-            result = fileset.getBaseDirectory().toPath().
-                    resolve(filename).toFile();
-
-            if (result == null || !result.exists()) {
-                String srcdir =
-                    StandardBundlerParam.SOURCE_DIR.fetchFrom(params);
-
-                if (srcdir != null) {
-                    result = new File(srcdir + File.separator + filename);
-                }
-            }
-        }
-
-        return result;
-    }
-
-    static String getMainClassFromModule(Map<String, ? super Object> params) {
-        String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
-        if (mainModule != null)  {
-
-            int index = mainModule.indexOf("/");
-            if (index > 0) {
-                return mainModule.substring(index + 1);
-            } else {
-                ModuleDescriptor descriptor =
-                        JLinkBundlerHelper.getMainModuleDescription(params);
-                if (descriptor != null) {
-                    Optional<String> mainClass = descriptor.mainClass();
-                    if (mainClass.isPresent()) {
-                        Log.verbose(MessageFormat.format(I18N.getString(
-                                    "message.module-class"),
-                                    mainClass.get(),
-                                    JLinkBundlerHelper.getMainModule(params)));
-                        return mainClass.get();
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    static String getMainModule(Map<String, ? super Object> params) {
-        String result = null;
-        String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
-
-        if (mainModule != null) {
-            int index = mainModule.indexOf("/");
-
-            if (index > 0) {
-                result = mainModule.substring(0, index);
-            } else {
-                result = mainModule;
-            }
-        }
-
-        return result;
-    }
-
-    static void execute(Map<String, ? super Object> params,
-            AbstractAppImageBuilder imageBuilder)
-            throws IOException, Exception {
-
-        List<Path> modulePath =
-                StandardBundlerParam.MODULE_PATH.fetchFrom(params);
-        Set<String> addModules =
-                StandardBundlerParam.ADD_MODULES.fetchFrom(params);
-        Set<String> limitModules =
-                StandardBundlerParam.LIMIT_MODULES.fetchFrom(params);
-        Path outputDir = imageBuilder.getRuntimeRoot();
-        File mainJar = getMainJar(params);
-        ModFile.ModType mainJarType = ModFile.ModType.Unknown;
-
-        if (mainJar != null) {
-            mainJarType = new ModFile(mainJar).getModType();
-        } else if (StandardBundlerParam.MODULE.fetchFrom(params) == null) {
-            // user specified only main class, all jars will be on the classpath
-            mainJarType = ModFile.ModType.UnnamedJar;
-        }
-
-        boolean bindServices =
-                StandardBundlerParam.BIND_SERVICES.fetchFrom(params);
-
-        // Modules
-        String mainModule = getMainModule(params);
-        if (mainModule == null) {
-            if (mainJarType == ModFile.ModType.UnnamedJar) {
-                if (addModules.isEmpty()) {
-                    // The default for an unnamed jar is ALL_DEFAULT
-                    addModules.add(ModuleHelper.ALL_DEFAULT);
-                }
-            } else if (mainJarType == ModFile.ModType.Unknown ||
-                    mainJarType == ModFile.ModType.ModularJar) {
-                addModules.add(ModuleHelper.ALL_DEFAULT);
-            }
-        }
-
-        Set<String> modules = new ModuleHelper(
-                modulePath, addModules, limitModules).modules();
-
-        if (mainModule != null) {
-            modules.add(mainModule);
-        }
-
-        runJLink(outputDir, modulePath, modules, limitModules,
-                new HashMap<String,String>(), bindServices);
-
-        imageBuilder.prepareApplicationFiles(params);
-    }
-
-
-    // Returns the path to the JDK modules in the user defined module path.
-    static Path findPathOfModule( List<Path> modulePath, String moduleName) {
-
-        for (Path path : modulePath) {
-            Path moduleNamePath = path.resolve(moduleName);
-
-            if (Files.exists(moduleNamePath)) {
-                return path;
-            }
-        }
-
-        return null;
-    }
-
-    static ModuleDescriptor getMainModuleDescription(Map<String, ? super Object> params) {
-        boolean hasModule = params.containsKey(StandardBundlerParam.MODULE.getID());
-        if (hasModule) {
-            List<Path> modulePath = StandardBundlerParam.MODULE_PATH.fetchFrom(params);
-            if (!modulePath.isEmpty()) {
-                ModuleFinder finder = ModuleFinder.of(modulePath.toArray(new Path[0]));
-                String mainModule = JLinkBundlerHelper.getMainModule(params);
-                Optional<ModuleReference> omref = finder.find(mainModule);
-                if (omref.isPresent()) {
-                    return omref.get().descriptor();
-                }
-            }
-        }
-
-        return null;
-    }
-
-    /*
-     * Returns the set of modules that would be visible by default for
-     * a non-modular-aware application consisting of the given elements.
-     */
-    private static Set<String> getDefaultModules(
-            Collection<Path> paths, Collection<String> addModules) {
-
-        // the modules in the run-time image that export an API
-        Stream<String> systemRoots = ModuleFinder.ofSystem().findAll().stream()
-                .map(ModuleReference::descriptor)
-                .filter(JLinkBundlerHelper::exportsAPI)
-                .map(ModuleDescriptor::name);
-
-        Set<String> roots = Stream.concat(systemRoots,
-                 addModules.stream()).collect(Collectors.toSet());
-
-        ModuleFinder finder = createModuleFinder(paths);
-
-        return Configuration.empty()
-                .resolveAndBind(finder, ModuleFinder.of(), roots)
-                .modules()
-                .stream()
-                .map(ResolvedModule::name)
-                .collect(Collectors.toSet());
-    }
-
-    /*
-     * Returns true if the given module exports an API to all module.
-     */
-    private static boolean exportsAPI(ModuleDescriptor descriptor) {
-        return descriptor.exports()
-                .stream()
-                .anyMatch(e -> !e.isQualified());
-    }
-
-    private static ModuleFinder createModuleFinder(Collection<Path> modulePath) {
-        return ModuleFinder.compose(
-                ModulePath.of(JarFile.runtimeVersion(), true,
-                        modulePath.toArray(Path[]::new)),
-                ModuleFinder.ofSystem());
-    }
-
-    private static class ModuleHelper {
-        // The token for "all modules on the module path".
-        private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
-
-        // The token for "all valid runtime modules".
-        static final String ALL_DEFAULT = "ALL-DEFAULT";
-
-        private final Set<String> modules = new HashSet<>();
-        ModuleHelper(List<Path> paths, Set<String> addModules,
-                Set<String> limitModules) {
-            boolean addAllModulePath = false;
-            boolean addDefaultMods = false;
-
-            for (Iterator<String> iterator = addModules.iterator();
-                    iterator.hasNext();) {
-                String module = iterator.next();
-
-                switch (module) {
-                    case ALL_MODULE_PATH:
-                        iterator.remove();
-                        addAllModulePath = true;
-                        break;
-                    case ALL_DEFAULT:
-                        iterator.remove();
-                        addDefaultMods = true;
-                        break;
-                    default:
-                        this.modules.add(module);
-                }
-            }
-
-            if (addAllModulePath) {
-                this.modules.addAll(getModuleNamesFromPath(paths));
-            } else if (addDefaultMods) {
-                this.modules.addAll(getDefaultModules(
-                        paths, addModules));
-            }
-        }
-
-        Set<String> modules() {
-            return modules;
-        }
-
-        private static Set<String> getModuleNamesFromPath(List<Path> paths) {
-
-            return createModuleFinder(paths)
-                    .findAll()
-                    .stream()
-                    .map(ModuleReference::descriptor)
-                    .map(ModuleDescriptor::name)
-                    .collect(Collectors.toSet());
-        }
-    }
-
-    private static void runJLink(Path output, List<Path> modulePath,
-            Set<String> modules, Set<String> limitModules,
-            HashMap<String, String> user, boolean bindServices)
-            throws PackagerException {
-
-        // This is just to ensure jlink is given a non-existant directory
-        // The passed in output path should be non-existant or empty directory
-        try {
-            IOUtils.deleteRecursive(output.toFile());
-        } catch (IOException ioe) {
-            throw new PackagerException(ioe);
-        }
-
-        ArrayList<String> args = new ArrayList<String>();
-        args.add("--output");
-        args.add(output.toString());
-        if (modulePath != null && !modulePath.isEmpty()) {
-            args.add("--module-path");
-            args.add(getPathList(modulePath));
-        }
-        if (modules != null && !modules.isEmpty()) {
-            args.add("--add-modules");
-            args.add(getStringList(modules));
-        }
-        if (limitModules != null && !limitModules.isEmpty()) {
-            args.add("--limit-modules");
-            args.add(getStringList(limitModules));
-        }
-        if (user != null && !user.isEmpty()) {
-            for (Map.Entry<String, String> entry : user.entrySet()) {
-                args.add(entry.getKey());
-                args.add(entry.getValue());
-            }
-        } else {
-            args.add("--strip-native-commands");
-            args.add("--strip-debug");
-            args.add("--no-man-pages");
-            args.add("--no-header-files");
-            if (bindServices) {
-                args.add("--bind-services");
-            }
-        }
-
-        StringWriter writer = new StringWriter();
-        PrintWriter pw = new PrintWriter(writer);
-
-        Log.verbose("jlink arguments: " + args);
-        int retVal = JLINK_TOOL.run(pw, pw, args.toArray(new String[0]));
-        String jlinkOut = writer.toString();
-
-        if (retVal != 0) {
-            throw new PackagerException("error.jlink.failed" , jlinkOut);
-        } else if (jlinkOut.length() > 0) {
-            Log.verbose("jlink output: " + jlinkOut);
-        }
-    }
-
-    private static String getPathList(List<Path> pathList) {
-        String ret = null;
-        for (Path p : pathList) {
-            String s =  Matcher.quoteReplacement(p.toString());
-            if (ret == null) {
-                ret = s;
-            } else {
-                ret += File.pathSeparator +  s;
-            }
-        }
-        return ret;
-    }
-
-    private static String getStringList(Set<String> strings) {
-        String ret = null;
-        for (String s : strings) {
-            if (ret == null) {
-                ret = s;
-            } else {
-                ret += "," + s;
-            }
-        }
-        return (ret == null) ? null : Matcher.quoteReplacement(ret);
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/JPackageToolProvider.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, 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.PrintWriter;
-import java.util.spi.ToolProvider;
-
-/**
- * JPackageToolProvider
- *
- * This is the ToolProvider implementation exported
- * to java.util.spi.ToolProvider and ultimately javax.tools.ToolProvider
- */
-public class JPackageToolProvider implements ToolProvider {
-
-    public String name() {
-        return "jpackage";
-    }
-
-    public synchronized int run(
-            PrintWriter out, PrintWriter err, String... args) {
-        try {
-            return new jdk.jpackage.main.Main().execute(out, err, args);
-        } catch (RuntimeException re) {
-            Log.error(re.getMessage());
-            Log.verbose(re);
-            return 1;
-        }
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Log.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2011, 2019, 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.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-
-/**
- * Log
- *
- * General purpose logging mechanism.
- */
-public class Log {
-    public static class Logger {
-        private boolean verbose = false;
-        private PrintWriter out = null;
-        private PrintWriter err = null;
-
-        // verbose defaults to true unless environment variable JPACKAGE_DEBUG
-        // is set to true.
-        // Then it is only set to true by using --verbose jpackage option
-
-        public Logger() {
-            verbose = ("true".equals(System.getenv("JPACKAGE_DEBUG")));
-        }
-
-        public void setVerbose() {
-            verbose = true;
-        }
-
-        public boolean isVerbose() {
-            return verbose;
-        }
-
-        public void setPrintWriter(PrintWriter out, PrintWriter err) {
-            this.out = out;
-            this.err = err;
-        }
-
-        public void flush() {
-            if (out != null) {
-                out.flush();
-            }
-
-            if (err != null) {
-                err.flush();
-            }
-        }
-
-        public void info(String msg) {
-            if (out != null) {
-                out.println(msg);
-            } else {
-                System.out.println(msg);
-            }
-        }
-
-        public void error(String msg) {
-            if (err != null) {
-                err.println(msg);
-            } else {
-                System.err.println(msg);
-            }
-        }
-
-        public void verbose(Throwable t) {
-            if (out != null && verbose) {
-                t.printStackTrace(out);
-            } else if (verbose) {
-                t.printStackTrace(System.out);
-            }
-        }
-
-        public void verbose(String msg) {
-            if (out != null && verbose) {
-                out.println(msg);
-            } else if (verbose) {
-                System.out.println(msg);
-            }
-        }
-    }
-
-    private static Logger delegate = null;
-
-    public static void setLogger(Logger logger) {
-        delegate = (logger != null) ? logger : new Logger();
-    }
-
-    public static void flush() {
-        if (delegate != null) {
-            delegate.flush();
-        }
-    }
-
-    public static void info(String msg) {
-        if (delegate != null) {
-           delegate.info(msg);
-        }
-    }
-
-    public static void error(String msg) {
-        if (delegate != null) {
-            delegate.error(msg);
-        }
-    }
-
-    public static void setVerbose() {
-        if (delegate != null) {
-            delegate.setVerbose();
-        }
-    }
-
-    public static boolean isVerbose() {
-        return (delegate != null) ? delegate.isVerbose() : false;
-    }
-
-    public static void verbose(String msg) {
-        if (delegate != null) {
-           delegate.verbose(msg);
-        }
-    }
-
-    public static void verbose(Throwable t) {
-        if (delegate != null) {
-           delegate.verbose(t);
-        }
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ModFile.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2016, 2019, 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.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-final class ModFile {
-    private final String filename;
-    private final ModType moduleType;
-
-    enum JarType {All, UnnamedJar, ModularJar}
-    enum ModType {
-            Unknown, UnnamedJar, ModularJar, Jmod, ExplodedModule}
-
-    ModFile(File aFile) {
-        super();
-        filename = aFile.getPath();
-        moduleType = getModType(aFile);
-    }
-
-    String getModName() {
-        File file = new File(getFileName());
-        // do not try to remove extension for directories
-        return moduleType == ModType.ExplodedModule ?
-                file.getName() : getFileWithoutExtension(file.getName());
-    }
-
-    String getFileName() {
-        return filename;
-    }
-
-    ModType getModType() {
-        return moduleType;
-    }
-
-    private static ModType getModType(File aFile) {
-        ModType result = ModType.Unknown;
-        String filename = aFile.getAbsolutePath();
-
-        if (aFile.isFile()) {
-            if (filename.endsWith(".jmod")) {
-                result = ModType.Jmod;
-            }
-            else if (filename.endsWith(".jar")) {
-                JarType status = isModularJar(filename);
-
-                if (status == JarType.ModularJar) {
-                    result = ModType.ModularJar;
-                }
-                else if (status == JarType.UnnamedJar) {
-                    result = ModType.UnnamedJar;
-                }
-            }
-        }
-        else if (aFile.isDirectory()) {
-            File moduleInfo = new File(
-                    filename + File.separator + "module-info.class");
-
-            if (moduleInfo.exists()) {
-                result = ModType.ExplodedModule;
-            }
-        }
-
-        return result;
-    }
-
-    private static JarType isModularJar(String FileName) {
-        JarType result = JarType.All;
-
-        try (ZipInputStream zip =
-                    new ZipInputStream(new FileInputStream(FileName))) {
-            result = JarType.UnnamedJar;
-
-            for (ZipEntry entry = zip.getNextEntry(); entry != null;
-                    entry = zip.getNextEntry()) {
-                if (entry.getName().matches("module-info.class")) {
-                    result = JarType.ModularJar;
-                    break;
-                }
-            }
-        } catch (IOException ex) {
-        }
-
-        return result;
-    }
-
-    private static String getFileWithoutExtension(String FileName) {
-        return FileName.replaceFirst("[.][^.]+$", "");
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2019, 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.*;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import static jdk.jpackage.internal.StandardBundlerParam.RESOURCE_DIR;
-import jdk.jpackage.internal.resources.ResourceLocator;
-
-/**
- * Resource file that may have the default value supplied by jpackage. It can be
- * overridden by a file from resource directory set with {@code --resource-dir}
- * jpackage parameter.
- *
- * Resource has default name and public name. Default name is the name of a file
- * in {@code jdk.jpackage.internal.resources} package that provides the default
- * value of the resource.
- *
- * Public name is a path relative to resource directory to a file with custom
- * value of the resource.
- *
- * Use #setPublicName to set the public name.
- *
- * If #setPublicName was not called, name of file passed in #saveToFile function
- * will be used as a public name.
- *
- * Use #setExternal to set arbitrary file as a source of resource. If non-null
- * value was passed in #setExternal call that value will be used as a path to file
- * to copy in the destination file passed in #saveToFile function call.
- */
-final class OverridableResource {
-
-    OverridableResource(String defaultName) {
-        this.defaultName = defaultName;
-    }
-
-    OverridableResource setSubstitutionData(Map<String, String> v) {
-        if (v != null) {
-            // Disconnect `v`
-            substitutionData = new HashMap<>(v);
-        } else {
-            substitutionData = null;
-        }
-        return this;
-    }
-
-    OverridableResource setCategory(String v) {
-        category = v;
-        return this;
-    }
-
-    OverridableResource setResourceDir(Path v) {
-        resourceDir = v;
-        return this;
-    }
-
-    OverridableResource setResourceDir(File v) {
-        return setResourceDir(toPath(v));
-    }
-
-    /**
-     * Set name of file to look for in resource dir.
-     *
-     * @return this
-     */
-    OverridableResource setPublicName(Path v) {
-        publicName = v;
-        return this;
-    }
-
-    OverridableResource setPublicName(String v) {
-        return setPublicName(Path.of(v));
-    }
-
-    OverridableResource setExternal(Path v) {
-        externalPath = v;
-        return this;
-    }
-
-    OverridableResource setExternal(File v) {
-        return setExternal(toPath(v));
-    }
-
-    void saveToFile(Path dest) throws IOException {
-        final String printableCategory;
-        if (category != null) {
-            printableCategory = String.format("[%s]", category);
-        } else {
-            printableCategory = "";
-        }
-
-        if (externalPath != null && externalPath.toFile().exists()) {
-            Log.verbose(MessageFormat.format(I18N.getString(
-                    "message.using-custom-resource-from-file"),
-                    printableCategory,
-                    externalPath.toAbsolutePath().normalize()));
-
-            try (InputStream in = Files.newInputStream(externalPath)) {
-                processResourceStream(in, dest);
-            }
-            return;
-        }
-
-        final Path resourceName = Optional.ofNullable(publicName).orElse(
-                dest.getFileName());
-
-        if (resourceDir != null) {
-            final Path customResource = resourceDir.resolve(resourceName);
-            if (customResource.toFile().exists()) {
-                Log.verbose(MessageFormat.format(I18N.getString(
-                        "message.using-custom-resource"), printableCategory,
-                        resourceDir.normalize().toAbsolutePath().relativize(
-                                customResource.normalize().toAbsolutePath())));
-
-                try (InputStream in = Files.newInputStream(customResource)) {
-                    processResourceStream(in, dest);
-                }
-                return;
-            }
-        }
-
-        if (defaultName != null) {
-            Log.verbose(MessageFormat.format(
-                    I18N.getString("message.using-default-resource"),
-                    defaultName, printableCategory, resourceName));
-
-            try (InputStream in = readDefault(defaultName)) {
-                processResourceStream(in, dest);
-            }
-        }
-    }
-
-    void saveToFile(File dest) throws IOException {
-        saveToFile(dest.toPath());
-    }
-
-    static InputStream readDefault(String resourceName) {
-        return ResourceLocator.class.getResourceAsStream(resourceName);
-    }
-
-    static OverridableResource createResource(String defaultName,
-            Map<String, ? super Object> params) {
-        return new OverridableResource(defaultName).setResourceDir(
-                RESOURCE_DIR.fetchFrom(params));
-    }
-
-    private static List<String> substitute(Stream<String> lines,
-            Map<String, String> substitutionData) {
-        return lines.map(line -> {
-            String result = line;
-            for (var entry : substitutionData.entrySet()) {
-                result = result.replace(entry.getKey(), Optional.ofNullable(
-                        entry.getValue()).orElse(""));
-            }
-            return result;
-        }).collect(Collectors.toList());
-    }
-
-    private static Path toPath(File v) {
-        if (v != null) {
-            return v.toPath();
-        }
-        return null;
-    }
-
-    private void processResourceStream(InputStream rawResource, Path dest)
-            throws IOException {
-        if (substitutionData == null) {
-            Files.createDirectories(dest.getParent());
-            Files.copy(rawResource, dest, StandardCopyOption.REPLACE_EXISTING);
-        } else {
-            // Utf8 in and out
-            try (BufferedReader reader = new BufferedReader(
-                    new InputStreamReader(rawResource, StandardCharsets.UTF_8))) {
-                Files.createDirectories(dest.getParent());
-                Files.write(dest, substitute(reader.lines(), substitutionData));
-            }
-        }
-    }
-
-    private Map<String, String> substitutionData;
-    private String category;
-    private Path resourceDir;
-    private Path publicName;
-    private Path externalPath;
-    private final String defaultName;
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PackagerException.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2011, 2019, 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.text.MessageFormat;
-import java.util.ResourceBundle;
-
-public class PackagerException extends Exception {
-    private static final long serialVersionUID = 1L;
-    private static final ResourceBundle bundle = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MainResources");
-
-    public PackagerException(Throwable cause) {
-        super(cause);
-    }
-
-    public PackagerException(String key, Throwable cause) {
-        super(bundle.getString(key), cause);
-    }
-
-    public PackagerException(String key) {
-        super(bundle.getString(key));
-    }
-
-    public PackagerException(String key, String ... arguments) {
-        super(MessageFormat.format(
-                bundle.getString(key), (Object[]) arguments));
-    }
-
-    public PackagerException(
-            Throwable cause, String key, String ... arguments) {
-        super(MessageFormat.format(bundle.getString(key),
-                (Object[]) arguments), cause);
-    }
-
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PathGroup.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 2019, 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.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.BiFunction;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-
-/**
- * Group of paths.
- * Each path in the group is assigned a unique id.
- */
-final class PathGroup {
-    PathGroup(Map<Object, Path> paths) {
-        entries = new HashMap<>(paths);
-    }
-
-    Path getPath(Object id) {
-        if (id == null) {
-            throw new NullPointerException();
-        }
-        return entries.get(id);
-    }
-
-    void setPath(Object id, Path path) {
-        if (path != null) {
-            entries.put(id, path);
-        } else {
-            entries.remove(id);
-        }
-    }
-
-    /**
-     * All configured entries.
-     */
-    List<Path> paths() {
-        return entries.values().stream().collect(Collectors.toList());
-    }
-
-    /**
-     * Root entries.
-     */
-    List<Path> roots() {
-        // Sort by the number of path components in ascending order.
-        List<Map.Entry<Path, Path>> sorted = normalizedPaths().stream().sorted(
-                (a, b) -> a.getKey().getNameCount() - b.getKey().getNameCount()).collect(
-                        Collectors.toList());
-
-        // Returns `true` if `a` is a parent of `b`
-        BiFunction<Map.Entry<Path, Path>, Map.Entry<Path, Path>, Boolean> isParentOrSelf = (a, b) -> {
-            return a == b || b.getKey().startsWith(a.getKey());
-        };
-
-        return sorted.stream().filter(
-                v -> v == sorted.stream().sequential().filter(
-                        v2 -> isParentOrSelf.apply(v2, v)).findFirst().get()).map(
-                        v -> v.getValue()).collect(Collectors.toList());
-    }
-
-    long sizeInBytes() throws IOException {
-        long reply = 0;
-        for (Path dir : roots().stream().filter(f -> Files.isDirectory(f)).collect(
-                Collectors.toList())) {
-            try (Stream<Path> stream = Files.walk(dir)) {
-                reply += stream.filter(p -> Files.isRegularFile(p)).mapToLong(
-                        f -> f.toFile().length()).sum();
-            }
-        }
-        return reply;
-    }
-
-    PathGroup resolveAt(Path root) {
-        return new PathGroup(entries.entrySet().stream().collect(
-                Collectors.toMap(e -> e.getKey(),
-                        e -> root.resolve(e.getValue()))));
-    }
-
-    void copy(PathGroup dst) throws IOException {
-        copy(this, dst, null, false);
-    }
-
-    void move(PathGroup dst) throws IOException {
-        copy(this, dst, null, true);
-    }
-
-    void transform(PathGroup dst, TransformHandler handler) throws IOException {
-        copy(this, dst, handler, false);
-    }
-
-    static interface Facade<T> {
-        PathGroup pathGroup();
-
-        default Collection<Path> paths() {
-            return pathGroup().paths();
-        }
-
-        default List<Path> roots() {
-            return pathGroup().roots();
-        }
-
-        default long sizeInBytes() throws IOException {
-            return pathGroup().sizeInBytes();
-        }
-
-        T resolveAt(Path root);
-
-        default void copy(Facade<T> dst) throws IOException {
-            pathGroup().copy(dst.pathGroup());
-        }
-
-        default void move(Facade<T> dst) throws IOException {
-            pathGroup().move(dst.pathGroup());
-        }
-
-        default void transform(Facade<T> dst, TransformHandler handler) throws
-                IOException {
-            pathGroup().transform(dst.pathGroup(), handler);
-        }
-    }
-
-    static interface TransformHandler {
-        public void copyFile(Path src, Path dst) throws IOException;
-        public void createDirectory(Path dir) throws IOException;
-    }
-
-    private static void copy(PathGroup src, PathGroup dst,
-            TransformHandler handler, boolean move) throws IOException {
-        List<Map.Entry<Path, Path>> copyItems = new ArrayList<>();
-        List<Path> excludeItems = new ArrayList<>();
-
-        for (var id: src.entries.keySet()) {
-            Path srcPath = src.entries.get(id);
-            if (dst.entries.containsKey(id)) {
-                copyItems.add(Map.entry(srcPath, dst.entries.get(id)));
-            } else {
-                excludeItems.add(srcPath);
-            }
-        }
-
-        copy(move, copyItems, excludeItems, handler);
-    }
-
-    private static void copy(boolean move, List<Map.Entry<Path, Path>> entries,
-            List<Path> excludePaths, TransformHandler handler) throws
-            IOException {
-
-        if (handler == null) {
-            handler = new TransformHandler() {
-                @Override
-                public void copyFile(Path src, Path dst) throws IOException {
-                    Files.createDirectories(dst.getParent());
-                    if (move) {
-                        Files.move(src, dst);
-                    } else {
-                        Files.copy(src, dst);
-                    }
-                }
-
-                @Override
-                public void createDirectory(Path dir) throws IOException {
-                    Files.createDirectories(dir);
-                }
-            };
-        }
-
-        // destination -> source file mapping
-        Map<Path, Path> actions = new HashMap<>();
-        for (var action: entries) {
-            Path src = action.getKey();
-            Path dst = action.getValue();
-            if (src.toFile().isDirectory()) {
-               try (Stream<Path> stream = Files.walk(src)) {
-                   stream.sequential().forEach(path -> actions.put(dst.resolve(
-                            src.relativize(path)).normalize(), path));
-               }
-            } else {
-                actions.put(dst.normalize(), src);
-            }
-        }
-
-        for (var action : actions.entrySet()) {
-            Path dst = action.getKey();
-            Path src = action.getValue();
-
-            if (excludePaths.stream().anyMatch(src::startsWith)) {
-                continue;
-            }
-
-            if (src.equals(dst) || !src.toFile().exists()) {
-                continue;
-            }
-
-            if (src.toFile().isDirectory()) {
-                handler.createDirectory(dst);
-            } else {
-                handler.copyFile(src, dst);
-            }
-        }
-
-        if (move) {
-            // Delete source dirs.
-            for (var entry: entries) {
-                File srcFile = entry.getKey().toFile();
-                if (srcFile.isDirectory()) {
-                    IOUtils.deleteRecursive(srcFile);
-                }
-            }
-        }
-    }
-
-    private static Map.Entry<Path, Path> normalizedPath(Path v) {
-        final Path normalized;
-        if (!v.isAbsolute()) {
-            normalized = Path.of("./").resolve(v.normalize());
-        } else {
-            normalized = v.normalize();
-        }
-
-        return Map.entry(normalized, v);
-    }
-
-    private List<Map.Entry<Path, Path>> normalizedPaths() {
-        return entries.values().stream().map(PathGroup::normalizedPath).collect(
-                Collectors.toList());
-    }
-
-    private final Map<Object, Path> entries;
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Platform.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2016, 2019, 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.regex.Pattern;
-
-/**
- * Platform
- *
- * Use <code>Platform</code> to detect the operating system
- * that is currently running.
- *
- * Example:
- *
- *  Platform platform = Platform.getPlatform();
- *
- *  switch(platform) {
- *    case Platform.MAC: {
- *      // Do something
- *      break;
- *    }
- *    case Platform.WINDOWS:
- *    case Platform.LINUX: {
- *      // Do something else
- *    }
- *  }
- *
- */
-enum Platform {UNKNOWN, WINDOWS, LINUX, MAC;
-    private static final Platform platform;
-    private static final int majorVersion;
-    private static final int minorVersion;
-
-    static {
-        String os = System.getProperty("os.name").toLowerCase();
-
-        if (os.indexOf("win") >= 0) {
-            platform = Platform.WINDOWS;
-        }
-        else if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) {
-            platform = Platform.LINUX;
-        }
-        else if (os.indexOf("mac") >= 0) {
-            platform = Platform.MAC;
-        }
-        else {
-            platform = Platform.UNKNOWN;
-        }
-
-        String version = System.getProperty("os.version").toString();
-        String[] parts = version.split(Pattern.quote("."));
-
-        if (parts.length > 0) {
-            majorVersion = Integer.parseInt(parts[0]);
-
-            if (parts.length > 1) {
-                minorVersion = Integer.parseInt(parts[1]);
-            }
-            else {
-                minorVersion = -1;
-            }
-        }
-        else {
-            majorVersion = -1;
-            minorVersion = -1;
-        }
-    }
-
-    private Platform() {}
-
-    static Platform getPlatform() {
-        return platform;
-    }
-
-    static int getMajorVersion() {
-        return majorVersion;
-    }
-
-    static int getMinorVersion() {
-        return minorVersion;
-    }
-
-    static boolean isWindows() {
-        return getPlatform() == WINDOWS;
-    }
-
-    static boolean isMac() {
-        return getPlatform() == MAC;
-    }
-
-    static boolean isLinux() {
-        return getPlatform() == LINUX;
-    }
-
-    static RuntimeException throwUnknownPlatformError() {
-        throw new IllegalArgumentException("Unknown platform");
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PlatformPackage.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2019, 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.nio.file.Path;
-
-/**
- *
- * Platform package of an application.
- */
-interface PlatformPackage {
-    /**
-     * Platform-specific package name.
-     */
-    String name();
-
-    /**
-     * Root directory where sources for packaging tool should be stored
-     */
-    Path sourceRoot();
-
-    /**
-     * Source application layout from which to build the package.
-     */
-    ApplicationLayout sourceApplicationLayout();
-
-    /**
-     * Application layout of the installed package.
-     */
-    ApplicationLayout installedApplicationLayout();
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/RelativeFileSet.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.File;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-/**
- * RelativeFileSet
- *
- * A class encapsulating a directory and a set of files within it.
- */
-class RelativeFileSet {
-
-    private File basedir;
-    private Set<String> files = new LinkedHashSet<>();
-
-    RelativeFileSet(File base, Collection<File> files) {
-        basedir = base;
-        String baseAbsolute = basedir.getAbsolutePath();
-        for (File f: files) {
-            String absolute = f.getAbsolutePath();
-            if (!absolute.startsWith(baseAbsolute)) {
-                throw new RuntimeException("File " + f.getAbsolutePath() +
-                        " does not belong to " + baseAbsolute);
-            }
-            if (!absolute.equals(baseAbsolute)) {
-                    // possible in jpackage case
-                this.files.add(absolute.substring(baseAbsolute.length()+1));
-            }
-        }
-    }
-
-    RelativeFileSet(File base, Set<File> files) {
-        this(base, (Collection<File>) files);
-    }
-
-    File getBaseDirectory() {
-        return basedir;
-    }
-
-    Set<String> getIncludedFiles() {
-        return files;
-    }
-
-    @Override
-    public String toString() {
-        if (files.size() ==  1) {
-            return "" + basedir + File.pathSeparator + files;
-        }
-        return "RelativeFileSet {basedir:" + basedir
-                + ", files: {" + files + "}";
-    }
-
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ScriptRunner.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2019, 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.Files;
-import java.nio.file.Path;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-import static jdk.jpackage.internal.StandardBundlerParam.APP_NAME;
-import static jdk.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
-
-/**
- * Runs custom script from resource directory.
- */
-class ScriptRunner {
-    ScriptRunner() {
-        environment = new ProcessBuilder().environment();
-    }
-
-    ScriptRunner setResourceCategoryId(String v) {
-        resourceCategoryId = v;
-        return this;
-    }
-
-    ScriptRunner setDirectory(Path v) {
-        directory = v;
-        return this;
-    }
-
-    ScriptRunner setScriptNameSuffix(String v) {
-        scriptNameSuffix = v;
-        return this;
-    }
-
-    ScriptRunner addEnvironment(Map<String, String> v) {
-        environment.putAll(v);
-        return this;
-    }
-
-    ScriptRunner setEnvironmentVariable(String envVarName, String envVarValue) {
-        Objects.requireNonNull(envVarName);
-        if (envVarValue == null) {
-            environment.remove(envVarName);
-        } else {
-            environment.put(envVarName, envVarValue);
-        }
-        return this;
-    }
-
-    public void run(Map<String, ? super Object> params) throws IOException {
-        String scriptName = String.format("%s-%s%s", APP_NAME.fetchFrom(params),
-                scriptNameSuffix, scriptSuffix());
-        Path scriptPath = CONFIG_ROOT.fetchFrom(params).toPath().resolve(
-                scriptName);
-        createResource(null, params)
-                .setCategory(I18N.getString(resourceCategoryId))
-                .saveToFile(scriptPath);
-        if (!Files.exists(scriptPath)) {
-            return;
-        }
-
-        ProcessBuilder pb = new ProcessBuilder(shell(),
-                scriptPath.toAbsolutePath().toString());
-        Map<String, String> workEnvironment = pb.environment();
-        workEnvironment.clear();
-        workEnvironment.putAll(environment);
-
-        if (directory != null) {
-            pb.directory(directory.toFile());
-        }
-
-        Executor.of(pb).executeExpectSuccess();
-    }
-
-    private static String shell() {
-        if (Platform.isWindows()) {
-            return "cscript";
-        }
-        return Optional.ofNullable(System.getenv("SHELL")).orElseGet(() -> "sh");
-    }
-
-    private static String scriptSuffix() {
-        if (Platform.isWindows()) {
-            return ".wsf";
-        }
-        return ".sh";
-    }
-
-    private String scriptNameSuffix;
-    private String resourceCategoryId;
-    private Path directory;
-    private Map<String, String> environment;
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,790 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.File;
-import java.io.IOException;
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Version;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.ResourceBundle;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.jar.Attributes;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * StandardBundlerParam
- *
- * A parameter to a bundler.
- *
- * Also contains static definitions of all of the common bundler parameters.
- * (additional platform specific and mode specific bundler parameters
- * are defined in each of the specific bundlers)
- *
- * Also contains static methods that operate on maps of parameters.
- */
-class StandardBundlerParam<T> extends BundlerParamInfo<T> {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MainResources");
-    private static final String JAVABASEJMOD = "java.base.jmod";
-    private final static String DEFAULT_VERSION = "1.0";
-    private final static String DEFAULT_RELEASE = "1";
-
-    StandardBundlerParam(String id, Class<T> valueType,
-            Function<Map<String, ? super Object>, T> defaultValueFunction,
-            BiFunction<String, Map<String, ? super Object>, T> stringConverter)
-    {
-        this.id = id;
-        this.valueType = valueType;
-        this.defaultValueFunction = defaultValueFunction;
-        this.stringConverter = stringConverter;
-    }
-
-    static final StandardBundlerParam<RelativeFileSet> APP_RESOURCES =
-            new StandardBundlerParam<>(
-                    BundleParams.PARAM_APP_RESOURCES,
-                    RelativeFileSet.class,
-                    null, // no default.  Required parameter
-                    null  // no string translation,
-                          // tool must provide complex type
-            );
-
-    @SuppressWarnings("unchecked")
-    static final
-            StandardBundlerParam<List<RelativeFileSet>> APP_RESOURCES_LIST =
-            new StandardBundlerParam<>(
-                    BundleParams.PARAM_APP_RESOURCES + "List",
-                    (Class<List<RelativeFileSet>>) (Object) List.class,
-                    // Default is appResources, as a single item list
-                    p -> new ArrayList<>(Collections.singletonList(
-                            APP_RESOURCES.fetchFrom(p))),
-                    StandardBundlerParam::createAppResourcesListFromString
-            );
-
-    static final StandardBundlerParam<String> SOURCE_DIR =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.INPUT.getId(),
-                    String.class,
-                    p -> null,
-                    (s, p) -> {
-                        String value = String.valueOf(s);
-                        if (value.charAt(value.length() - 1) ==
-                                File.separatorChar) {
-                            return value.substring(0, value.length() - 1);
-                        }
-                        else {
-                            return value;
-                        }
-                    }
-            );
-
-    // note that each bundler is likely to replace this one with
-    // their own converter
-    static final StandardBundlerParam<RelativeFileSet> MAIN_JAR =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.MAIN_JAR.getId(),
-                    RelativeFileSet.class,
-                    params -> {
-                        extractMainClassInfoFromAppResources(params);
-                        return (RelativeFileSet) params.get("mainJar");
-                    },
-                    (s, p) -> getMainJar(s, p)
-            );
-
-    static final StandardBundlerParam<String> CLASSPATH =
-            new StandardBundlerParam<>(
-                    "classpath",
-                    String.class,
-                    params -> {
-                        extractMainClassInfoFromAppResources(params);
-                        String cp = (String) params.get("classpath");
-                        return cp == null ? "" : cp;
-                    },
-                    (s, p) -> s
-            );
-
-    static final StandardBundlerParam<String> MAIN_CLASS =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.APPCLASS.getId(),
-                    String.class,
-                    params -> {
-                        if (isRuntimeInstaller(params)) {
-                            return null;
-                        }
-                        extractMainClassInfoFromAppResources(params);
-                        String s = (String) params.get(
-                                BundleParams.PARAM_APPLICATION_CLASS);
-                        if (s == null) {
-                            s = JLinkBundlerHelper.getMainClassFromModule(
-                                    params);
-                        }
-                        return s;
-                    },
-                    (s, p) -> s
-            );
-
-    static final StandardBundlerParam<File> PREDEFINED_RUNTIME_IMAGE =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId(),
-                    File.class,
-                    params -> null,
-                    (s, p) -> new File(s)
-            );
-
-    static final StandardBundlerParam<String> APP_NAME =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.NAME.getId(),
-                    String.class,
-                    params -> {
-                        String s = MAIN_CLASS.fetchFrom(params);
-                        if (s != null) {
-                            int idx = s.lastIndexOf(".");
-                            if (idx >= 0) {
-                                return s.substring(idx+1);
-                            }
-                            return s;
-                        } else if (isRuntimeInstaller(params)) {
-                            File f = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
-                            if (f != null) {
-                                return f.getName();
-                            }
-                        }
-                        return null;
-                    },
-                    (s, p) -> s
-            );
-
-    static final StandardBundlerParam<File> ICON =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.ICON.getId(),
-                    File.class,
-                    params -> null,
-                    (s, p) -> new File(s)
-            );
-
-    static final StandardBundlerParam<String> VENDOR =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.VENDOR.getId(),
-                    String.class,
-                    params -> I18N.getString("param.vendor.default"),
-                    (s, p) -> s
-            );
-
-    static final StandardBundlerParam<String> DESCRIPTION =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.DESCRIPTION.getId(),
-                    String.class,
-                    params -> params.containsKey(APP_NAME.getID())
-                            ? APP_NAME.fetchFrom(params)
-                            : I18N.getString("param.description.default"),
-                    (s, p) -> s
-            );
-
-    static final StandardBundlerParam<String> COPYRIGHT =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.COPYRIGHT.getId(),
-                    String.class,
-                    params -> MessageFormat.format(I18N.getString(
-                            "param.copyright.default"), new Date()),
-                    (s, p) -> s
-            );
-
-    @SuppressWarnings("unchecked")
-    static final StandardBundlerParam<List<String>> ARGUMENTS =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.ARGUMENTS.getId(),
-                    (Class<List<String>>) (Object) List.class,
-                    params -> Collections.emptyList(),
-                    (s, p) -> null
-            );
-
-    @SuppressWarnings("unchecked")
-    static final StandardBundlerParam<List<String>> JAVA_OPTIONS =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.JAVA_OPTIONS.getId(),
-                    (Class<List<String>>) (Object) List.class,
-                    params -> Collections.emptyList(),
-                    (s, p) -> Arrays.asList(s.split("\n\n"))
-            );
-
-    // note that each bundler is likely to replace this one with
-    // their own converter
-    static final StandardBundlerParam<String> VERSION =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.VERSION.getId(),
-                    String.class,
-                    params -> getDefaultAppVersion(params),
-                    (s, p) -> s
-            );
-
-    static final StandardBundlerParam<String> RELEASE =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.RELEASE.getId(),
-                    String.class,
-                    params -> DEFAULT_RELEASE,
-                    (s, p) -> s
-            );
-
-    @SuppressWarnings("unchecked")
-    public static final StandardBundlerParam<String> LICENSE_FILE =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.LICENSE_FILE.getId(),
-                    String.class,
-                    params -> null,
-                    (s, p) -> s
-            );
-
-    static final StandardBundlerParam<File> TEMP_ROOT =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.TEMP_ROOT.getId(),
-                    File.class,
-                    params -> {
-                        try {
-                            return Files.createTempDirectory(
-                                    "jdk.jpackage").toFile();
-                        } catch (IOException ioe) {
-                            return null;
-                        }
-                    },
-                    (s, p) -> new File(s)
-            );
-
-    public static final StandardBundlerParam<File> CONFIG_ROOT =
-            new StandardBundlerParam<>(
-                "configRoot",
-                File.class,
-                params -> {
-                    File root =
-                            new File(TEMP_ROOT.fetchFrom(params), "config");
-                    root.mkdirs();
-                    return root;
-                },
-                (s, p) -> null
-            );
-
-    static final StandardBundlerParam<String> IDENTIFIER =
-            new StandardBundlerParam<>(
-                    "identifier.default",
-                    String.class,
-                    params -> {
-                        String s = MAIN_CLASS.fetchFrom(params);
-                        if (s == null) return null;
-
-                        int idx = s.lastIndexOf(".");
-                        if (idx >= 1) {
-                            return s.substring(0, idx);
-                        }
-                        return s;
-                    },
-                    (s, p) -> s
-            );
-
-    static final StandardBundlerParam<Boolean> BIND_SERVICES =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.BIND_SERVICES.getId(),
-                    Boolean.class,
-                    params -> false,
-                    (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
-                            true : Boolean.valueOf(s)
-            );
-
-
-    static final StandardBundlerParam<Boolean> VERBOSE  =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.VERBOSE.getId(),
-                    Boolean.class,
-                    params -> false,
-                    // valueOf(null) is false, and we actually do want null
-                    (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
-                            true : Boolean.valueOf(s)
-            );
-
-    static final StandardBundlerParam<File> RESOURCE_DIR =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.RESOURCE_DIR.getId(),
-                    File.class,
-                    params -> null,
-                    (s, p) -> new File(s)
-            );
-
-    static final BundlerParamInfo<String> INSTALL_DIR =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.INSTALL_DIR.getId(),
-                    String.class,
-                     params -> null,
-                    (s, p) -> s
-    );
-
-    static final StandardBundlerParam<File> PREDEFINED_APP_IMAGE =
-            new StandardBundlerParam<>(
-            Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId(),
-            File.class,
-            params -> null,
-            (s, p) -> new File(s));
-
-    @SuppressWarnings("unchecked")
-    static final StandardBundlerParam<List<Map<String, ? super Object>>> ADD_LAUNCHERS =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.ADD_LAUNCHER.getId(),
-                    (Class<List<Map<String, ? super Object>>>) (Object)
-                            List.class,
-                    params -> new ArrayList<>(1),
-                    // valueOf(null) is false, and we actually do want null
-                    (s, p) -> null
-            );
-
-    @SuppressWarnings("unchecked")
-    static final StandardBundlerParam
-            <List<Map<String, ? super Object>>> FILE_ASSOCIATIONS =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.FILE_ASSOCIATIONS.getId(),
-                    (Class<List<Map<String, ? super Object>>>) (Object)
-                            List.class,
-                    params -> new ArrayList<>(1),
-                    // valueOf(null) is false, and we actually do want null
-                    (s, p) -> null
-            );
-
-    @SuppressWarnings("unchecked")
-    static final StandardBundlerParam<List<String>> FA_EXTENSIONS =
-            new StandardBundlerParam<>(
-                    "fileAssociation.extension",
-                    (Class<List<String>>) (Object) List.class,
-                    params -> null, // null means not matched to an extension
-                    (s, p) -> Arrays.asList(s.split("(,|\\s)+"))
-            );
-
-    @SuppressWarnings("unchecked")
-    static final StandardBundlerParam<List<String>> FA_CONTENT_TYPE =
-            new StandardBundlerParam<>(
-                    "fileAssociation.contentType",
-                    (Class<List<String>>) (Object) List.class,
-                    params -> null,
-                            // null means not matched to a content/mime type
-                    (s, p) -> Arrays.asList(s.split("(,|\\s)+"))
-            );
-
-    static final StandardBundlerParam<String> FA_DESCRIPTION =
-            new StandardBundlerParam<>(
-                    "fileAssociation.description",
-                    String.class,
-                    params -> APP_NAME.fetchFrom(params) + " File",
-                    null
-            );
-
-    static final StandardBundlerParam<File> FA_ICON =
-            new StandardBundlerParam<>(
-                    "fileAssociation.icon",
-                    File.class,
-                    ICON::fetchFrom,
-                    (s, p) -> new File(s)
-            );
-
-    @SuppressWarnings("unchecked")
-    static final BundlerParamInfo<List<Path>> MODULE_PATH =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.MODULE_PATH.getId(),
-                    (Class<List<Path>>) (Object)List.class,
-                    p -> { return getDefaultModulePath(); },
-                    (s, p) -> {
-                        List<Path> modulePath = Arrays.asList(s
-                                .split(File.pathSeparator)).stream()
-                                .map(ss -> new File(ss).toPath())
-                                .collect(Collectors.toList());
-                        Path javaBasePath = null;
-                        if (modulePath != null) {
-                            javaBasePath = JLinkBundlerHelper
-                                    .findPathOfModule(modulePath, JAVABASEJMOD);
-                        } else {
-                            modulePath = new ArrayList<Path>();
-                        }
-
-                        // Add the default JDK module path to the module path.
-                        if (javaBasePath == null) {
-                            List<Path> jdkModulePath = getDefaultModulePath();
-
-                            if (jdkModulePath != null) {
-                                modulePath.addAll(jdkModulePath);
-                                javaBasePath =
-                                        JLinkBundlerHelper.findPathOfModule(
-                                        modulePath, JAVABASEJMOD);
-                            }
-                        }
-
-                        if (javaBasePath == null ||
-                                !Files.exists(javaBasePath)) {
-                            Log.error(String.format(I18N.getString(
-                                    "warning.no.jdk.modules.found")));
-                        }
-
-                        return modulePath;
-                    });
-
-    static final BundlerParamInfo<String> MODULE =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.MODULE.getId(),
-                    String.class,
-                    p -> null,
-                    (s, p) -> {
-                        return String.valueOf(s);
-                    });
-
-    @SuppressWarnings("unchecked")
-    static final BundlerParamInfo<Set<String>> ADD_MODULES =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.ADD_MODULES.getId(),
-                    (Class<Set<String>>) (Object) Set.class,
-                    p -> new LinkedHashSet<String>(),
-                    (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(",")))
-            );
-
-    @SuppressWarnings("unchecked")
-    static final BundlerParamInfo<Set<String>> LIMIT_MODULES =
-            new StandardBundlerParam<>(
-                    "limit-modules",
-                    (Class<Set<String>>) (Object) Set.class,
-                    p -> new LinkedHashSet<String>(),
-                    (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(",")))
-            );
-
-    static boolean isRuntimeInstaller(Map<String, ? super Object> params) {
-        if (params.containsKey(MODULE.getID()) ||
-                params.containsKey(MAIN_JAR.getID()) ||
-                params.containsKey(PREDEFINED_APP_IMAGE.getID())) {
-            return false; // we are building or are given an application
-        }
-        // runtime installer requires --runtime-image, if this is false
-        // here then we should have thrown error validating args.
-        return params.containsKey(PREDEFINED_RUNTIME_IMAGE.getID());
-    }
-
-    static File getPredefinedAppImage(Map<String, ? super Object> params) {
-        File applicationImage = null;
-        if (PREDEFINED_APP_IMAGE.fetchFrom(params) != null) {
-            applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params);
-            if (!applicationImage.exists()) {
-                throw new RuntimeException(
-                        MessageFormat.format(I18N.getString(
-                                "message.app-image-dir-does-not-exist"),
-                                PREDEFINED_APP_IMAGE.getID(),
-                                applicationImage.toString()));
-            }
-        }
-        return applicationImage;
-    }
-
-    static void copyPredefinedRuntimeImage(
-            Map<String, ? super Object> params,
-            AbstractAppImageBuilder appBuilder)
-            throws IOException , ConfigException {
-        File topImage = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params);
-        if (!topImage.exists()) {
-            throw new ConfigException(
-                    MessageFormat.format(I18N.getString(
-                    "message.runtime-image-dir-does-not-exist"),
-                    PREDEFINED_RUNTIME_IMAGE.getID(),
-                    topImage.toString()),
-                    MessageFormat.format(I18N.getString(
-                    "message.runtime-image-dir-does-not-exist.advice"),
-                    PREDEFINED_RUNTIME_IMAGE.getID()));
-        }
-        File image = appBuilder.getRuntimeImageDir(topImage);
-        // copy whole runtime, need to skip jmods and src.zip
-        final List<String> excludes = Arrays.asList("jmods", "src.zip");
-        IOUtils.copyRecursive(image.toPath(), appBuilder.getRuntimeRoot(), excludes);
-
-        // if module-path given - copy modules to appDir/mods
-        List<Path> modulePath =
-                StandardBundlerParam.MODULE_PATH.fetchFrom(params);
-        List<Path> defaultModulePath = getDefaultModulePath();
-        Path dest = appBuilder.getAppModsDir();
-
-        if (dest != null) {
-            for (Path mp : modulePath) {
-                if (!defaultModulePath.contains(mp)) {
-                    Files.createDirectories(dest);
-                    IOUtils.copyRecursive(mp, dest);
-                }
-            }
-        }
-
-        appBuilder.prepareApplicationFiles(params);
-    }
-
-    static void extractMainClassInfoFromAppResources(
-            Map<String, ? super Object> params) {
-        boolean hasMainClass = params.containsKey(MAIN_CLASS.getID());
-        boolean hasMainJar = params.containsKey(MAIN_JAR.getID());
-        boolean hasMainJarClassPath = params.containsKey(CLASSPATH.getID());
-        boolean hasModule = params.containsKey(MODULE.getID());
-
-        if (hasMainClass && hasMainJar && hasMainJarClassPath || hasModule ||
-                isRuntimeInstaller(params)) {
-            return;
-        }
-
-        // it's a pair.
-        // The [0] is the srcdir [1] is the file relative to sourcedir
-        List<String[]> filesToCheck = new ArrayList<>();
-
-        if (hasMainJar) {
-            RelativeFileSet rfs = MAIN_JAR.fetchFrom(params);
-            for (String s : rfs.getIncludedFiles()) {
-                filesToCheck.add(
-                        new String[] {rfs.getBaseDirectory().toString(), s});
-            }
-        } else if (hasMainJarClassPath) {
-            for (String s : CLASSPATH.fetchFrom(params).split("\\s+")) {
-                if (APP_RESOURCES.fetchFrom(params) != null) {
-                    filesToCheck.add(
-                            new String[] {APP_RESOURCES.fetchFrom(params)
-                            .getBaseDirectory().toString(), s});
-                }
-            }
-        } else {
-            List<RelativeFileSet> rfsl = APP_RESOURCES_LIST.fetchFrom(params);
-            if (rfsl == null || rfsl.isEmpty()) {
-                return;
-            }
-            for (RelativeFileSet rfs : rfsl) {
-                if (rfs == null) continue;
-
-                for (String s : rfs.getIncludedFiles()) {
-                    filesToCheck.add(
-                            new String[]{rfs.getBaseDirectory().toString(), s});
-                }
-            }
-        }
-
-        // presume the set iterates in-order
-        for (String[] fnames : filesToCheck) {
-            try {
-                // only sniff jars
-                if (!fnames[1].toLowerCase().endsWith(".jar")) continue;
-
-                File file = new File(fnames[0], fnames[1]);
-                // that actually exist
-                if (!file.exists()) continue;
-
-                try (JarFile jf = new JarFile(file)) {
-                    Manifest m = jf.getManifest();
-                    Attributes attrs = (m != null) ?
-                            m.getMainAttributes() : null;
-
-                    if (attrs != null) {
-                        if (!hasMainJar) {
-                            if (fnames[0] == null) {
-                                fnames[0] = file.getParentFile().toString();
-                            }
-                            params.put(MAIN_JAR.getID(), new RelativeFileSet(
-                                    new File(fnames[0]),
-                                    new LinkedHashSet<>(Collections
-                                    .singletonList(file))));
-                        }
-                        if (!hasMainJarClassPath) {
-                            String cp =
-                                    attrs.getValue(Attributes.Name.CLASS_PATH);
-                            params.put(CLASSPATH.getID(),
-                                    cp == null ? "" : cp);
-                        }
-                        break;
-                    }
-                }
-            } catch (IOException ignore) {
-                ignore.printStackTrace();
-            }
-        }
-    }
-
-    static void validateMainClassInfoFromAppResources(
-            Map<String, ? super Object> params) throws ConfigException {
-        boolean hasMainClass = params.containsKey(MAIN_CLASS.getID());
-        boolean hasMainJar = params.containsKey(MAIN_JAR.getID());
-        boolean hasMainJarClassPath = params.containsKey(CLASSPATH.getID());
-        boolean hasModule = params.containsKey(MODULE.getID());
-        boolean hasAppImage = params.containsKey(PREDEFINED_APP_IMAGE.getID());
-
-        if (hasMainClass && hasMainJar && hasMainJarClassPath ||
-               hasAppImage || isRuntimeInstaller(params)) {
-            return;
-        }
-        if (hasModule) {
-            if (JLinkBundlerHelper.getMainClassFromModule(params) == null) {
-                throw new ConfigException(
-                        I18N.getString("ERR_NoMainClass"), null);
-            }
-        } else {
-            extractMainClassInfoFromAppResources(params);
-
-            if (!params.containsKey(MAIN_CLASS.getID())) {
-                if (hasMainJar) {
-                    throw new ConfigException(
-                            MessageFormat.format(I18N.getString(
-                            "error.no-main-class-with-main-jar"),
-                            MAIN_JAR.fetchFrom(params)),
-                            MessageFormat.format(I18N.getString(
-                            "error.no-main-class-with-main-jar.advice"),
-                            MAIN_JAR.fetchFrom(params)));
-                } else {
-                    throw new ConfigException(
-                            I18N.getString("error.no-main-class"),
-                            I18N.getString("error.no-main-class.advice"));
-                }
-            }
-        }
-    }
-
-    private static List<RelativeFileSet>
-            createAppResourcesListFromString(String s,
-            Map<String, ? super Object> objectObjectMap) {
-        List<RelativeFileSet> result = new ArrayList<>();
-        for (String path : s.split("[:;]")) {
-            File f = new File(path);
-            if (f.getName().equals("*") || path.endsWith("/") ||
-                    path.endsWith("\\")) {
-                if (f.getName().equals("*")) {
-                    f = f.getParentFile();
-                }
-                Set<File> theFiles = new HashSet<>();
-                try {
-                    try (Stream<Path> stream = Files.walk(f.toPath())) {
-                        stream.filter(Files::isRegularFile)
-                                .forEach(p -> theFiles.add(p.toFile()));
-                    }
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-                result.add(new RelativeFileSet(f, theFiles));
-            } else {
-                result.add(new RelativeFileSet(f.getParentFile(),
-                        Collections.singleton(f)));
-            }
-        }
-        return result;
-    }
-
-    private static RelativeFileSet getMainJar(
-            String mainJarValue, Map<String, ? super Object> params) {
-        for (RelativeFileSet rfs : APP_RESOURCES_LIST.fetchFrom(params)) {
-            File appResourcesRoot = rfs.getBaseDirectory();
-            File mainJarFile = new File(appResourcesRoot, mainJarValue);
-
-            if (mainJarFile.exists()) {
-                return new RelativeFileSet(appResourcesRoot,
-                     new LinkedHashSet<>(Collections.singletonList(
-                     mainJarFile)));
-            }
-            mainJarFile = new File(mainJarValue);
-            if (mainJarFile.exists()) {
-                // absolute path for main-jar may fail is not legal
-                // below contains explicit error message.
-            } else {
-                List<Path> modulePath = MODULE_PATH.fetchFrom(params);
-                modulePath.removeAll(getDefaultModulePath());
-                if (!modulePath.isEmpty()) {
-                    Path modularJarPath = JLinkBundlerHelper.findPathOfModule(
-                            modulePath, mainJarValue);
-                    if (modularJarPath != null &&
-                            Files.exists(modularJarPath)) {
-                        return new RelativeFileSet(appResourcesRoot,
-                                new LinkedHashSet<>(Collections.singletonList(
-                                modularJarPath.toFile())));
-                    }
-                }
-            }
-        }
-
-        throw new IllegalArgumentException(
-                new ConfigException(MessageFormat.format(I18N.getString(
-                        "error.main-jar-does-not-exist"),
-                        mainJarValue), I18N.getString(
-                        "error.main-jar-does-not-exist.advice")));
-    }
-
-    static List<Path> getDefaultModulePath() {
-        List<Path> result = new ArrayList<Path>();
-        Path jdkModulePath = Paths.get(
-                System.getProperty("java.home"), "jmods").toAbsolutePath();
-
-        if (jdkModulePath != null && Files.exists(jdkModulePath)) {
-            result.add(jdkModulePath);
-        }
-        else {
-            // On a developer build the JDK Home isn't where we expect it
-            // relative to the jmods directory. Do some extra
-            // processing to find it.
-            Map<String, String> env = System.getenv();
-
-            if (env.containsKey("JDK_HOME")) {
-                jdkModulePath = Paths.get(env.get("JDK_HOME"),
-                        ".." + File.separator + "images"
-                        + File.separator + "jmods").toAbsolutePath();
-
-                if (jdkModulePath != null && Files.exists(jdkModulePath)) {
-                    result.add(jdkModulePath);
-                }
-            }
-        }
-
-        return result;
-    }
-
-    static String getDefaultAppVersion(Map<String, ? super Object> params) {
-        String appVersion = DEFAULT_VERSION;
-
-        ModuleDescriptor descriptor = JLinkBundlerHelper.getMainModuleDescription(params);
-        if (descriptor != null) {
-            Optional<Version> oversion = descriptor.version();
-            if (oversion.isPresent()) {
-                Log.verbose(MessageFormat.format(I18N.getString(
-                        "message.module-version"),
-                        oversion.get().toString(),
-                        JLinkBundlerHelper.getMainModule(params)));
-                appVersion = oversion.get().toString();
-            }
-        }
-
-        return appVersion;
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ToolValidator.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2019, 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.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.stream.Stream;
-
-
-public final class ToolValidator {
-
-    ToolValidator(String tool) {
-        this(Path.of(tool));
-    }
-
-    ToolValidator(Path toolPath) {
-        this.toolPath = toolPath;
-        args = new ArrayList<>();
-
-        if (Platform.getPlatform() == Platform.LINUX) {
-            setCommandLine("--version");
-        }
-
-        setToolNotFoundErrorHandler(null);
-        setToolOldVersionErrorHandler(null);
-    }
-
-    ToolValidator setCommandLine(String... args) {
-        this.args = List.of(args);
-        return this;
-    }
-
-    ToolValidator setMinimalVersion(Comparable<String> v) {
-        minimalVersion = v;
-        return this;
-    }
-
-    ToolValidator setVersionParser(Function<Stream<String>, String> v) {
-        versionParser = v;
-        return this;
-    }
-
-    ToolValidator setToolNotFoundErrorHandler(
-            BiFunction<String, IOException, ConfigException> v) {
-        toolNotFoundErrorHandler = v;
-        return this;
-    }
-
-    ToolValidator setToolOldVersionErrorHandler(BiFunction<String, String, ConfigException> v) {
-        toolOldVersionErrorHandler = v;
-        return this;
-    }
-
-    ConfigException validate() {
-        List<String> cmdline = new ArrayList<>();
-        cmdline.add(toolPath.toString());
-        cmdline.addAll(args);
-
-        String name = toolPath.getFileName().toString();
-        try {
-            ProcessBuilder pb = new ProcessBuilder(cmdline);
-            AtomicBoolean canUseTool = new AtomicBoolean();
-            if (minimalVersion == null) {
-                // No version check.
-                canUseTool.setPlain(true);
-            }
-
-            String[] version = new String[1];
-            Executor.of(pb).setOutputConsumer(lines -> {
-                if (versionParser != null && minimalVersion != null) {
-                    version[0] = versionParser.apply(lines);
-                    if (minimalVersion.compareTo(version[0]) < 0) {
-                        canUseTool.setPlain(true);
-                    }
-                }
-            }).execute();
-
-            if (!canUseTool.getPlain()) {
-                if (toolOldVersionErrorHandler != null) {
-                    return toolOldVersionErrorHandler.apply(name, version[0]);
-                }
-                return new ConfigException(MessageFormat.format(I18N.getString(
-                        "error.tool-old-version"), name, minimalVersion),
-                        MessageFormat.format(I18N.getString(
-                                "error.tool-old-version.advice"), name,
-                                minimalVersion));
-            }
-        } catch (IOException e) {
-            if (toolNotFoundErrorHandler != null) {
-                return toolNotFoundErrorHandler.apply(name, e);
-            }
-            return new ConfigException(MessageFormat.format(I18N.getString(
-                    "error.tool-not-found"), name, e.getMessage()),
-                    MessageFormat.format(I18N.getString(
-                            "error.tool-not-found.advice"), name), e);
-        }
-
-        // All good. Tool can be used.
-        return null;
-    }
-
-    private final Path toolPath;
-    private List<String> args;
-    private Comparable<String> minimalVersion;
-    private Function<Stream<String>, String> versionParser;
-    private BiFunction<String, IOException, ConfigException> toolNotFoundErrorHandler;
-    private BiFunction<String, String, ConfigException> toolOldVersionErrorHandler;
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ValidOptions.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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.HashSet;
-import java.util.Map;
-import java.util.Set;
-import jdk.jpackage.internal.Arguments.CLIOptions;
-
-/**
- * ValidOptions
- *
- * Two basic methods for validating command line options.
- *
- * initArgs()
- *      Computes the Map of valid options for each mode on this Platform.
- *
- * checkIfSupported(CLIOptions arg)
- *      Determine if the given arg is valid on this platform.
- *
- * checkIfImageSupported(CLIOptions arg)
- *      Determine if the given arg is valid for creating app image.
- *
- * checkIfInstallerSupported(CLIOptions arg)
- *      Determine if the given arg is valid for creating installer.
- *
- */
-class ValidOptions {
-
-    enum USE {
-        ALL,        // valid in all cases
-        LAUNCHER,   // valid when creating a launcher
-        INSTALL     // valid when creating an installer
-    }
-
-    private static final HashMap<String, USE> options = new HashMap<>();
-
-
-    // initializing list of mandatory arguments
-    static {
-        options.put(CLIOptions.NAME.getId(), USE.ALL);
-        options.put(CLIOptions.VERSION.getId(), USE.ALL);
-        options.put(CLIOptions.OUTPUT.getId(), USE.ALL);
-        options.put(CLIOptions.TEMP_ROOT.getId(), USE.ALL);
-        options.put(CLIOptions.VERBOSE.getId(), USE.ALL);
-        options.put(CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId(), USE.ALL);
-        options.put(CLIOptions.RESOURCE_DIR.getId(), USE.ALL);
-        options.put(CLIOptions.DESCRIPTION.getId(), USE.ALL);
-        options.put(CLIOptions.VENDOR.getId(), USE.ALL);
-        options.put(CLIOptions.COPYRIGHT.getId(), USE.ALL);
-        options.put(CLIOptions.PACKAGE_TYPE.getId(), USE.ALL);
-
-        options.put(CLIOptions.INPUT.getId(), USE.LAUNCHER);
-        options.put(CLIOptions.MODULE.getId(), USE.LAUNCHER);
-        options.put(CLIOptions.MODULE_PATH.getId(), USE.LAUNCHER);
-        options.put(CLIOptions.ADD_MODULES.getId(), USE.LAUNCHER);
-        options.put(CLIOptions.MAIN_JAR.getId(), USE.LAUNCHER);
-        options.put(CLIOptions.APPCLASS.getId(), USE.LAUNCHER);
-        options.put(CLIOptions.ICON.getId(), USE.LAUNCHER);
-        options.put(CLIOptions.ARGUMENTS.getId(), USE.LAUNCHER);
-        options.put(CLIOptions.JAVA_OPTIONS.getId(), USE.LAUNCHER);
-        options.put(CLIOptions.ADD_LAUNCHER.getId(), USE.LAUNCHER);
-        options.put(CLIOptions.BIND_SERVICES.getId(), USE.LAUNCHER);
-
-        options.put(CLIOptions.LICENSE_FILE.getId(), USE.INSTALL);
-        options.put(CLIOptions.INSTALL_DIR.getId(), USE.INSTALL);
-        options.put(CLIOptions.PREDEFINED_APP_IMAGE.getId(), USE.INSTALL);
-
-        options.put(CLIOptions.FILE_ASSOCIATIONS.getId(),
-            (Platform.getPlatform() == Platform.MAC) ?  USE.ALL : USE.INSTALL);
-
-        if (Platform.getPlatform() == Platform.WINDOWS) {
-            options.put(CLIOptions.WIN_CONSOLE_HINT.getId(), USE.LAUNCHER);
-
-            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_DIR_CHOOSER.getId(), USE.INSTALL);
-            options.put(CLIOptions.WIN_UPGRADE_UUID.getId(), USE.INSTALL);
-            options.put(CLIOptions.WIN_PER_USER_INSTALLATION.getId(),
-                    USE.INSTALL);
-        }
-
-        if (Platform.getPlatform() == Platform.MAC) {
-            options.put(CLIOptions.MAC_SIGN.getId(), USE.ALL);
-            options.put(CLIOptions.MAC_BUNDLE_NAME.getId(), USE.ALL);
-            options.put(CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(), USE.ALL);
-            options.put(CLIOptions.MAC_BUNDLE_SIGNING_PREFIX.getId(),
-                    USE.ALL);
-            options.put(CLIOptions.MAC_SIGNING_KEY_NAME.getId(), USE.ALL);
-            options.put(CLIOptions.MAC_SIGNING_KEYCHAIN.getId(), USE.ALL);
-            options.put(CLIOptions.MAC_APP_STORE_ENTITLEMENTS.getId(),
-                    USE.ALL);
-        }
-
-        if (Platform.getPlatform() == Platform.LINUX) {
-            options.put(CLIOptions.LINUX_BUNDLE_NAME.getId(), USE.INSTALL);
-            options.put(CLIOptions.LINUX_DEB_MAINTAINER.getId(), USE.INSTALL);
-            options.put(CLIOptions.LINUX_CATEGORY.getId(), USE.INSTALL);
-            options.put(CLIOptions.LINUX_RPM_LICENSE_TYPE.getId(), USE.INSTALL);
-            options.put(CLIOptions.LINUX_PACKAGE_DEPENDENCIES.getId(),
-                    USE.INSTALL);
-            options.put(CLIOptions.LINUX_MENU_GROUP.getId(), USE.INSTALL);
-            options.put(CLIOptions.RELEASE.getId(), USE.INSTALL);
-            options.put(CLIOptions.LINUX_SHORTCUT_HINT.getId(), USE.INSTALL);
-        }
-    }
-
-    static boolean checkIfSupported(CLIOptions arg) {
-        return options.containsKey(arg.getId());
-    }
-
-    static boolean checkIfImageSupported(CLIOptions arg) {
-        USE use = options.get(arg.getId());
-        return USE.ALL == use || USE.LAUNCHER == use;
-    }
-
-    static boolean checkIfInstallerSupported(CLIOptions arg) {
-        USE use = options.get(arg.getId());
-        return USE.ALL == use || USE.INSTALL == use;
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-MSG_Help=Usage: jpackage <options>\n\
-\n\
-Sample usages:\n\
---------------\n\
-\    Generate a non-modular application image:\n\
-\        jpackage -t app-image -d destdir -i inputdir -n name \\\n\
-\            --main-class className --main-jar MyJar.jar\n\
-\    Generate a modular application image:\n\
-\        jpackage -t app-image -n name -p modulePath \\\n\
-\            -m moduleName/className\n\
-\        To provide your own options to jlink, run jlink separately:\n\
-\            jlink --output appRuntimeImage -p ModulePath -m moduleName \\\n\
-\                --no-header-files [<additional jlink options>...]\n\
-\            jpackage -t app-image -n name \\\n\
-\                -m moduleName/className --runtime-image appRuntimeImage\n\
-\    Generate an application package:\n\
-\        jpackage -t <type> -n name \\\n\
-\            -p modulePath -m moduleName/className\n\
-\        jpackage -t <type> -i inputdir -n name \\\n\
-\            --main-class package.ClassName --main-jar MyJar.jar\n\
-\        jpackage -t <type> -n name \\\n\
-\            --app-image <app image dir>\n\
-\    Generate a Java runtime package:\n\
-\        jpackage -n name --runtime-image <runtime-image>\n\
-\n\
-Generic Options:\n\
-\  @<filename> \n\
-\          Read options and/or mode from a file \n\
-\          This option can be used multiple times.\n\
-\  --type -t <type> \n\
-\          The type of package to create\n\
-\          Valid values are: {1} \n\
-\          If this option is not specified a platform dependent\n\
-\          default type will be created.\n\
-\  --app-version <version>\n\
-\          Version of the application and/or package\n\
-\  --copyright <copyright string>\n\
-\          Copyright for the application\n\
-\  --description <description string>\n\
-\          Description of the application\n\
-\  --help -h \n\
-\          Print the usage text with a list and description of each valid\n\
-\          option for the current platform to the output stream, and exit\n\
-\  --name -n <name>\n\
-\          Name of the application and/or package\n\
-\  --dest -d <destination path>\n\
-\          Path where generated output file is placed\n\
-\          Defaults to the current working directory.\n\
-\          (absolute path or relative to the current directory)\n\
-\  --temp <file path>\n\
-\          Path of a new or empty directory used to create temporary files\n\
-\          (absolute path or relative to the current directory)\n\
-\          If specified, the temp dir will not be removed upon the task\n\
-\          completion and must be removed manually\n\
-\          If not specified, a temporary directory will be created and\n\
-\          removed upon the task completion.\n\
-\  --vendor <vendor string>\n\
-\          Vendor of the application\n\
-\  --verbose\n\
-\          Enables verbose output\n\
-\  --version\n\
-\          Print the product version to the output stream and exit\n\
-\n\
-\Options for creating the runtime image:\n\
-\  --add-modules <module name>[,<module name>...]\n\
-\          A comma (",") separated list of modules to add.\n\
-\          This module list, along with the main module (if specified)\n\
-\          will be passed to jlink as the --add-module argument.\n\
-\          if not specified, either just the main module (if --module is\n\
-\          specified), or the default set of modules (if --main-jar is \n\
-\          specified) are used.\n\
-\          This option can be used multiple times.\n\
-\  --module-path -p <module path>...\n\
-\          A {0} separated list of paths\n\
-\          Each path is either a directory of modules or the path to a\n\
-\          modular jar.\n\
-\          (each path is absolute or relative to the current directory)\n\
-\          This option can be used multiple times.\n\
-\  --bind-services \n\
-\          Pass on --bind-services option to jlink (which will link in \n\
-\          service provider modules and their dependences) \n\
-\  --runtime-image <file path>\n\
-\          Path of the predefined runtime image that will be copied into\n\
-\          the application image\n\
-\          (absolute path or relative to the current directory)\n\
-\          If --runtime-image is not specified, jpackage will run jlink to\n\
-\          create the runtime image using options:\n\
-\          --strip-debug, --no-header-files, --no-man-pages, and\n\
-\          --strip-native-commands.  --bind-services will also be added if\n\
-\          --add-modules is not specified.\n\
-\n\
-\Options for creating the application image:\n\
-\  --icon <icon file path>\n\
-\          Path of the icon of the application package\n\
-\          (absolute path or relative to the current directory)\n\
-\  --input -i <input path>\n\
-\          Path of the input directory that contains the files to be packaged\n\
-\          (absolute path or relative to the current directory)\n\
-\          All files in the input directory will be packaged into the\n\
-\          application image.\n\
-\n\
-\Options for creating the application launcher(s):\n\
-\  --add-launcher <launcher name>=<file path>\n\
-\          Name of launcher, and a path to a Properties file that contains\n\
-\          a list of key, value pairs\n\
-\          (absolute path or relative to the current directory)\n\
-\          The keys "module", "main-jar", "main-class",\n\
-\          "arguments", "java-options", "app-version", "icon", and\n\
-\          "win-console" can be used.\n\
-\          These options are added to, or used to overwrite, the original\n\
-\          command line options to build an additional alternative launcher.\n\
-\          The main application launcher will be built from the command line\n\
-\          options. Additional alternative launchers can be built using\n\
-\          this option, and this option can be used multiple times to\n\
-\          build multiple additional launchers. \n\
-\  --arguments <main class arguments>\n\
-\          Command line arguments to pass to the main class if no command\n\
-\          line arguments are given to the launcher\n\
-\          This option can be used multiple times.\n\
-\  --java-options <java options>\n\
-\          Options to pass to the Java runtime\n\
-\          This option can be used multiple times.\n\
-\  --main-class <class name>\n\
-\          Qualified name of the application main class to execute\n\
-\          This option can only be used if --main-jar is specified.\n\
-\  --main-jar <main jar file>\n\
-\          The main JAR of the application; containing the main class\n\
-\          (specified as a path relative to the input path)\n\
-\          Either --module or --main-jar option can be specified but not\n\
-\          both.\n\
-\  --module -m <module name>[/<main class>]\n\
-\          The main module (and optionally main class) of the application\n\
-\          This module must be located on the module path.\n\
-\          When this option is specified, the main module will be linked\n\
-\          in the Java runtime image.  Either --module or --main-jar\n\
-\          option can be specified but not both.\n\
-{2}\n\
-\Options for creating the application package:\n\
-\  --app-image <file path>\n\
-\          Location of the predefined application image that is used\n\
-\          to build an installable package\n\
-\          (absolute path or relative to the current directory)\n\
-\  --file-associations <file path>\n\
-\          Path to a Properties file that contains list of key, value pairs\n\
-\          (absolute path or relative to the current directory)\n\
-\          The keys "extension", "mime-type", "icon", and "description"\n\
-\          can be used to describe the association.\n\
-\          This option can be used multiple times.\n\
-\  --install-dir <file path>\n\
-\          {4}\
-\  --license-file <file path>\n\
-\          Path to the license file\n\
-\          (absolute path or relative to the current directory)\n\
-\  --resource-dir <path>\n\
-\          Path to override jpackage resources\n\
-\          Icons, template files, and other resources of jpackage can be\n\
-\          over-ridden by adding replacement resources to this directory.\n\
-\          (absolute path or relative to the current directory)\n\
-\  --runtime-image <file-path>\n\
-\          Path of the predefined runtime image to install\n\
-\          (absolute path or relative to the current directory)\n\
-\          Option is required when creating a runtime package.\n\
-\n\
-\Platform dependent options for creating the application package:\n\
-{3}
-
-MSG_Help_win_launcher=\
-\n\
-\Platform dependent option for creating the application launcher:\n\
-\  --win-console\n\
-\          Creates a console launcher for the application, should be\n\
-\          specified for application which requires console interactions\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\
-\          Adds the application to the system menu\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\
-\  --win-upgrade-uuid <id string>\n\
-\          UUID associated with upgrades for this package\n\
-
-MSG_Help_win_install_dir=\
-\Relative sub-path under the default installation location\n\
-
-MSG_Help_mac_launcher=\
-\  --mac-package-identifier <ID string>\n\
-\          An identifier that uniquely identifies the application for macOS\n\
-\          Defaults to the main class name.\n\
-\          May only use alphanumeric (A-Z,a-z,0-9), hyphen (-),\n\
-\          and period (.) characters.\n\
-\  --mac-package-name <name string>\n\
-\          Name of the application as it appears in the Menu Bar\n\
-\          This can be different from the application name.\n\
-\          This name must be less than 16 characters long and be suitable for\n\
-\          displaying in the menu bar and the application Info window.\n\
-\          Defaults to the application name.\n\
-\  --mac-package-signing-prefix <prefix string>\n\
-\          When signing the application package, this value is prefixed\n\
-\          to all components that need to be signed that don't have\n\
-\          an existing package identifier.\n\
-\  --mac-sign\n\
-\          Request that the package be signed\n\
-\  --mac-signing-keychain <file path>\n\
-\          Path of the keychain to search for the signing identity\n\
-\          (absolute path or relative to the current directory).\n\
-\          If not specified, the standard keychains are used.\n\
-\  --mac-signing-key-user-name <team name>\n\
-\          Team name portion in Apple signing identities' names.\n\
-\          For example "Developer ID Application: "\n\
-
-MSG_Help_linux_install=\
-\  --linux-package-name <package name>\n\
-\          Name for Linux package, defaults to the application name\n\
-\  --linux-deb-maintainer <email address>\n\
-\          Maintainer for .deb package\n\
-\  --linux-menu-group <menu-group-name>\n\
-\          Menu group this application is placed in\n\
-\  --linux-package-deps\n\
-\          Required packages or capabilities for the application\n\
-\  --linux-rpm-license-type <type string>\n\
-\          Type of the license ("License: <value>" of the RPM .spec)\n\
-\  --linux-app-release <release value>\n\
-\          Release value of the RPM <name>.spec file or \n\
-\          Debian revision value of the DEB control file.\n\
-\  --linux-app-category <category value>\n\
-\          Group value of the RPM <name>.spec file or \n\
-\          Section value of DEB control file.\n\
-\  --linux-shortcut\n\
-\          Creates a shortcut for the application\n\
-
-MSG_Help_mac_linux_install_dir=\
-\Absolute path of the installation directory of the application\n\
-
-MSG_Help_default_install_dir=\
-\Absolute path of the installation directory of the application on OS X\n\
-\          or Linux. Relative sub-path of the installation location of\n\
-\          the application such as "Program Files" or "AppData" on Windows.\n\
-
-MSG_Help_no_args=Usage: jpackage <mode> <options>\n\
-\Use jpackage --help (or -h) for a list of possible options\
-
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_ja.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-MSG_Help=Usage: jpackage <options>\n\
-\n\
-Sample usages:\n\
---------------\n\
-\    Generate a non-modular application image:\n\
-\        jpackage -t app-image -d destdir -i inputdir -n name \\\n\
-\            --main-class className --main-jar MyJar.jar\n\
-\    Generate a modular application image:\n\
-\        jpackage -t app-image -n name -p modulePath \\\n\
-\            -m moduleName/className\n\
-\        To provide your own options to jlink, run jlink separately:\n\
-\            jlink --output appRuntimeImage -p ModulePath -m moduleName \\\n\
-\                --no-header-files [<additional jlink options>...]\n\
-\            jpackage -t app-image -n name \\\n\
-\                -m moduleName/className --runtime-image appRuntimeImage\n\
-\    Generate an application package:\n\
-\        jpackage -t <type> -n name \\\n\
-\            -p modulePath -m moduleName/className\n\
-\        jpackage -t <type> -i inputdir -n name \\\n\
-\            --main-class package.ClassName --main-jar MyJar.jar\n\
-\        jpackage -t <type> -n name \\\n\
-\            --app-image <app image dir>\n\
-\    Generate a Java runtime package:\n\
-\        jpackage -n name --runtime-image <runtime-image>\n\
-\n\
-Generic Options:\n\
-\  @<filename> \n\
-\          Read options and/or mode from a file \n\
-\          This option can be used multiple times.\n\
-\  --type -t <type> \n\
-\          The type of package to create\n\
-\          Valid values are: {1} \n\
-\          If this option is not specified a platform dependent\n\
-\          default type will be created.\n\
-\  --app-version <version>\n\
-\          Version of the application and/or package\n\
-\  --copyright <copyright string>\n\
-\          Copyright for the application\n\
-\  --description <description string>\n\
-\          Description of the application\n\
-\  --help -h \n\
-\          Print the usage text with a list and description of each valid\n\
-\          option for the current platform to the output stream, and exit\n\
-\  --name -n <name>\n\
-\          Name of the application and/or package\n\
-\  --dest -d <destination path>\n\
-\          Path where generated output file is placed\n\
-\          Defaults to the current working directory.\n\
-\          (absolute path or relative to the current directory)\n\
-\  --temp <file path>\n\
-\          Path of a new or empty directory used to create temporary files\n\
-\          (absolute path or relative to the current directory)\n\
-\          If specified, the temp dir will not be removed upon the task\n\
-\          completion and must be removed manually\n\
-\          If not specified, a temporary directory will be created and\n\
-\          removed upon the task completion.\n\
-\  --vendor <vendor string>\n\
-\          Vendor of the application\n\
-\  --verbose\n\
-\          Enables verbose output\n\
-\  --version\n\
-\          Print the product version to the output stream and exit\n\
-\n\
-\Options for creating the runtime image:\n\
-\  --add-modules <module name>[,<module name>...]\n\
-\          A comma (",") separated list of modules to add.\n\
-\          This module list, along with the main module (if specified)\n\
-\          will be passed to jlink as the --add-module argument.\n\
-\          if not specified, either just the main module (if --module is\n\
-\          specified), or the default set of modules (if --main-jar is \n\
-\          specified) are used.\n\
-\          This option can be used multiple times.\n\
-\  --module-path -p <module path>...\n\
-\          A {0} separated list of paths\n\
-\          Each path is either a directory of modules or the path to a\n\
-\          modular jar.\n\
-\          (each path is absolute or relative to the current directory)\n\
-\          This option can be used multiple times.\n\
-\  --bind-services \n\
-\          Pass on --bind-services option to jlink (which will link in \n\
-\          service provider modules and their dependences) \n\
-\  --runtime-image <file path>\n\
-\          Path of the predefined runtime image that will be copied into\n\
-\          the application image\n\
-\          (absolute path or relative to the current directory)\n\
-\          If --runtime-image is not specified, jpackage will run jlink to\n\
-\          create the runtime image using options:\n\
-\          --strip-debug, --no-header-files, --no-man-pages, and\n\
-\          --strip-native-commands.  --bind-services will also be added if\n\
-\          --add-modules is not specified.\n\
-\n\
-\Options for creating the application image:\n\
-\  --icon <icon file path>\n\
-\          Path of the icon of the application package\n\
-\          (absolute path or relative to the current directory)\n\
-\  --input -i <input path>\n\
-\          Path of the input directory that contains the files to be packaged\n\
-\          (absolute path or relative to the current directory)\n\
-\          All files in the input directory will be packaged into the\n\
-\          application image.\n\
-\n\
-\Options for creating the application launcher(s):\n\
-\  --add-launcher <launcher name>=<file path>\n\
-\          Name of launcher, and a path to a Properties file that contains\n\
-\          a list of key, value pairs\n\
-\          (absolute path or relative to the current directory)\n\
-\          The keys "module", "main-jar", "main-class",\n\
-\          "arguments", "java-options", "app-version", "icon", and\n\
-\          "win-console" can be used.\n\
-\          These options are added to, or used to overwrite, the original\n\
-\          command line options to build an additional alternative launcher.\n\
-\          The main application launcher will be built from the command line\n\
-\          options. Additional alternative launchers can be built using\n\
-\          this option, and this option can be used multiple times to\n\
-\          build multiple additional launchers. \n\
-\  --arguments <main class arguments>\n\
-\          Command line arguments to pass to the main class if no command\n\
-\          line arguments are given to the launcher\n\
-\          This option can be used multiple times.\n\
-\  --java-options <java options>\n\
-\          Options to pass to the Java runtime\n\
-\          This option can be used multiple times.\n\
-\  --main-class <class name>\n\
-\          Qualified name of the application main class to execute\n\
-\          This option can only be used if --main-jar is specified.\n\
-\  --main-jar <main jar file>\n\
-\          The main JAR of the application; containing the main class\n\
-\          (specified as a path relative to the input path)\n\
-\          Either --module or --main-jar option can be specified but not\n\
-\          both.\n\
-\  --module -m <module name>[/<main class>]\n\
-\          The main module (and optionally main class) of the application\n\
-\          This module must be located on the module path.\n\
-\          When this option is specified, the main module will be linked\n\
-\          in the Java runtime image.  Either --module or --main-jar\n\
-\          option can be specified but not both.\n\
-{2}\n\
-\Options for creating the application package:\n\
-\  --app-image <file path>\n\
-\          Location of the predefined application image that is used\n\
-\          to build an installable package\n\
-\          (absolute path or relative to the current directory)\n\
-\  --file-associations <file path>\n\
-\          Path to a Properties file that contains list of key, value pairs\n\
-\          (absolute path or relative to the current directory)\n\
-\          The keys "extension", "mime-type", "icon", and "description"\n\
-\          can be used to describe the association.\n\
-\          This option can be used multiple times.\n\
-\  --install-dir <file path>\n\
-\          {4}\
-\  --license-file <file path>\n\
-\          Path to the license file\n\
-\          (absolute path or relative to the current directory)\n\
-\  --resource-dir <path>\n\
-\          Path to override jpackage resources\n\
-\          Icons, template files, and other resources of jpackage can be\n\
-\          over-ridden by adding replacement resources to this directory.\n\
-\          (absolute path or relative to the current directory)\n\
-\  --runtime-image <file-path>\n\
-\          Path of the predefined runtime image to install\n\
-\          (absolute path or relative to the current directory)\n\
-\          Option is required when creating a runtime package.\n\
-\n\
-\Platform dependent options for creating the application package:\n\
-{3}
-
-MSG_Help_win_launcher=\
-\n\
-\Platform dependent option for creating the application launcher:\n\
-\  --win-console\n\
-\          Creates a console launcher for the application, should be\n\
-\          specified for application which requires console interactions\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\
-\          Adds the application to the system menu\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\
-\  --win-upgrade-uuid <id string>\n\
-\          UUID associated with upgrades for this package\n\
-
-MSG_Help_win_install_dir=\
-\Relative sub-path under the default installation location\n\
-
-MSG_Help_mac_launcher=\
-\  --mac-package-identifier <ID string>\n\
-\          An identifier that uniquely identifies the application for macOS\n\
-\          Defaults to the main class name.\n\
-\          May only use alphanumeric (A-Z,a-z,0-9), hyphen (-),\n\
-\          and period (.) characters.\n\
-\  --mac-package-name <name string>\n\
-\          Name of the application as it appears in the Menu Bar\n\
-\          This can be different from the application name.\n\
-\          This name must be less than 16 characters long and be suitable for\n\
-\          displaying in the menu bar and the application Info window.\n\
-\          Defaults to the application name.\n\
-\  --mac-package-signing-prefix <prefix string>\n\
-\          When signing the application package, this value is prefixed\n\
-\          to all components that need to be signed that don't have\n\
-\          an existing package identifier.\n\
-\  --mac-sign\n\
-\          Request that the package be signed\n\
-\  --mac-signing-keychain <file path>\n\
-\          Path of the keychain to search for the signing identity\n\
-\          (absolute path or relative to the current directory).\n\
-\          If not specified, the standard keychains are used.\n\
-\  --mac-signing-key-user-name <team name>\n\
-\          Team name portion in Apple signing identities' names.\n\
-\          For example "Developer ID Application: "\n\
-
-MSG_Help_linux_install=\
-\  --linux-package-name <package name>\n\
-\          Name for Linux package, defaults to the application name\n\
-\  --linux-deb-maintainer <email address>\n\
-\          Maintainer for .deb package\n\
-\  --linux-menu-group <menu-group-name>\n\
-\          Menu group this application is placed in\n\
-\  --linux-package-deps\n\
-\          Required packages or capabilities for the application\n\
-\  --linux-rpm-license-type <type string>\n\
-\          Type of the license ("License: <value>" of the RPM .spec)\n\
-\  --linux-app-release <release value>\n\
-\          Release value of the RPM <name>.spec file or \n\
-\          Debian revision value of the DEB control file.\n\
-\  --linux-app-category <category value>\n\
-\          Group value of the RPM <name>.spec file or \n\
-\          Section value of DEB control file.\n\
-\  --linux-shortcut\n\
-\          Creates a shortcut for the application\n\
-
-MSG_Help_mac_linux_install_dir=\
-\Absolute path of the installation directory of the application\n\
-
-MSG_Help_default_install_dir=\
-\Absolute path of the installation directory of the application on OS X\n\
-\          or Linux. Relative sub-path of the installation location of\n\
-\          the application such as "Program Files" or "AppData" on Windows.\n\
-
-MSG_Help_no_args=Usage: jpackage <mode> <options>\n\
-\Use jpackage --help (or -h) for a list of possible options\
-
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_zh_CN.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-MSG_Help=Usage: jpackage <options>\n\
-\n\
-Sample usages:\n\
---------------\n\
-\    Generate a non-modular application image:\n\
-\        jpackage -t app-image -d destdir -i inputdir -n name \\\n\
-\            --main-class className --main-jar MyJar.jar\n\
-\    Generate a modular application image:\n\
-\        jpackage -t app-image -n name -p modulePath \\\n\
-\            -m moduleName/className\n\
-\        To provide your own options to jlink, run jlink separately:\n\
-\            jlink --output appRuntimeImage -p ModulePath -m moduleName \\\n\
-\                --no-header-files [<additional jlink options>...]\n\
-\            jpackage -t app-image -n name \\\n\
-\                -m moduleName/className --runtime-image appRuntimeImage\n\
-\    Generate an application package:\n\
-\        jpackage -t <type> -n name \\\n\
-\            -p modulePath -m moduleName/className\n\
-\        jpackage -t <type> -i inputdir -n name \\\n\
-\            --main-class package.ClassName --main-jar MyJar.jar\n\
-\        jpackage -t <type> -n name \\\n\
-\            --app-image <app image dir>\n\
-\    Generate a Java runtime package:\n\
-\        jpackage -n name --runtime-image <runtime-image>\n\
-\n\
-Generic Options:\n\
-\  @<filename> \n\
-\          Read options and/or mode from a file \n\
-\          This option can be used multiple times.\n\
-\  --type -t <type> \n\
-\          The type of package to create\n\
-\          Valid values are: {1} \n\
-\          If this option is not specified a platform dependent\n\
-\          default type will be created.\n\
-\  --app-version <version>\n\
-\          Version of the application and/or package\n\
-\  --copyright <copyright string>\n\
-\          Copyright for the application\n\
-\  --description <description string>\n\
-\          Description of the application\n\
-\  --help -h \n\
-\          Print the usage text with a list and description of each valid\n\
-\          option for the current platform to the output stream, and exit\n\
-\  --name -n <name>\n\
-\          Name of the application and/or package\n\
-\  --dest -d <destination path>\n\
-\          Path where generated output file is placed\n\
-\          Defaults to the current working directory.\n\
-\          (absolute path or relative to the current directory)\n\
-\  --temp <file path>\n\
-\          Path of a new or empty directory used to create temporary files\n\
-\          (absolute path or relative to the current directory)\n\
-\          If specified, the temp dir will not be removed upon the task\n\
-\          completion and must be removed manually\n\
-\          If not specified, a temporary directory will be created and\n\
-\          removed upon the task completion.\n\
-\  --vendor <vendor string>\n\
-\          Vendor of the application\n\
-\  --verbose\n\
-\          Enables verbose output\n\
-\  --version\n\
-\          Print the product version to the output stream and exit\n\
-\n\
-\Options for creating the runtime image:\n\
-\  --add-modules <module name>[,<module name>...]\n\
-\          A comma (",") separated list of modules to add.\n\
-\          This module list, along with the main module (if specified)\n\
-\          will be passed to jlink as the --add-module argument.\n\
-\          if not specified, either just the main module (if --module is\n\
-\          specified), or the default set of modules (if --main-jar is \n\
-\          specified) are used.\n\
-\          This option can be used multiple times.\n\
-\  --module-path -p <module path>...\n\
-\          A {0} separated list of paths\n\
-\          Each path is either a directory of modules or the path to a\n\
-\          modular jar.\n\
-\          (each path is absolute or relative to the current directory)\n\
-\          This option can be used multiple times.\n\
-\  --bind-services \n\
-\          Pass on --bind-services option to jlink (which will link in \n\
-\          service provider modules and their dependences) \n\
-\  --runtime-image <file path>\n\
-\          Path of the predefined runtime image that will be copied into\n\
-\          the application image\n\
-\          (absolute path or relative to the current directory)\n\
-\          If --runtime-image is not specified, jpackage will run jlink to\n\
-\          create the runtime image using options:\n\
-\          --strip-debug, --no-header-files, --no-man-pages, and\n\
-\          --strip-native-commands.  --bind-services will also be added if\n\
-\          --add-modules is not specified.\n\
-\n\
-\Options for creating the application image:\n\
-\  --icon <icon file path>\n\
-\          Path of the icon of the application package\n\
-\          (absolute path or relative to the current directory)\n\
-\  --input -i <input path>\n\
-\          Path of the input directory that contains the files to be packaged\n\
-\          (absolute path or relative to the current directory)\n\
-\          All files in the input directory will be packaged into the\n\
-\          application image.\n\
-\n\
-\Options for creating the application launcher(s):\n\
-\  --add-launcher <launcher name>=<file path>\n\
-\          Name of launcher, and a path to a Properties file that contains\n\
-\          a list of key, value pairs\n\
-\          (absolute path or relative to the current directory)\n\
-\          The keys "module", "main-jar", "main-class",\n\
-\          "arguments", "java-options", "app-version", "icon", and\n\
-\          "win-console" can be used.\n\
-\          These options are added to, or used to overwrite, the original\n\
-\          command line options to build an additional alternative launcher.\n\
-\          The main application launcher will be built from the command line\n\
-\          options. Additional alternative launchers can be built using\n\
-\          this option, and this option can be used multiple times to\n\
-\          build multiple additional launchers. \n\
-\  --arguments <main class arguments>\n\
-\          Command line arguments to pass to the main class if no command\n\
-\          line arguments are given to the launcher\n\
-\          This option can be used multiple times.\n\
-\  --java-options <java options>\n\
-\          Options to pass to the Java runtime\n\
-\          This option can be used multiple times.\n\
-\  --main-class <class name>\n\
-\          Qualified name of the application main class to execute\n\
-\          This option can only be used if --main-jar is specified.\n\
-\  --main-jar <main jar file>\n\
-\          The main JAR of the application; containing the main class\n\
-\          (specified as a path relative to the input path)\n\
-\          Either --module or --main-jar option can be specified but not\n\
-\          both.\n\
-\  --module -m <module name>[/<main class>]\n\
-\          The main module (and optionally main class) of the application\n\
-\          This module must be located on the module path.\n\
-\          When this option is specified, the main module will be linked\n\
-\          in the Java runtime image.  Either --module or --main-jar\n\
-\          option can be specified but not both.\n\
-{2}\n\
-\Options for creating the application package:\n\
-\  --app-image <file path>\n\
-\          Location of the predefined application image that is used\n\
-\          to build an installable package\n\
-\          (absolute path or relative to the current directory)\n\
-\  --file-associations <file path>\n\
-\          Path to a Properties file that contains list of key, value pairs\n\
-\          (absolute path or relative to the current directory)\n\
-\          The keys "extension", "mime-type", "icon", and "description"\n\
-\          can be used to describe the association.\n\
-\          This option can be used multiple times.\n\
-\  --install-dir <file path>\n\
-\          {4}\
-\  --license-file <file path>\n\
-\          Path to the license file\n\
-\          (absolute path or relative to the current directory)\n\
-\  --resource-dir <path>\n\
-\          Path to override jpackage resources\n\
-\          Icons, template files, and other resources of jpackage can be\n\
-\          over-ridden by adding replacement resources to this directory.\n\
-\          (absolute path or relative to the current directory)\n\
-\  --runtime-image <file-path>\n\
-\          Path of the predefined runtime image to install\n\
-\          (absolute path or relative to the current directory)\n\
-\          Option is required when creating a runtime package.\n\
-\n\
-\Platform dependent options for creating the application package:\n\
-{3}
-
-MSG_Help_win_launcher=\
-\n\
-\Platform dependent option for creating the application launcher:\n\
-\  --win-console\n\
-\          Creates a console launcher for the application, should be\n\
-\          specified for application which requires console interactions\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\
-\          Adds the application to the system menu\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\
-\  --win-upgrade-uuid <id string>\n\
-\          UUID associated with upgrades for this package\n\
-
-MSG_Help_win_install_dir=\
-\Relative sub-path under the default installation location\n\
-
-MSG_Help_mac_launcher=\
-\  --mac-package-identifier <ID string>\n\
-\          An identifier that uniquely identifies the application for macOS\n\
-\          Defaults to the main class name.\n\
-\          May only use alphanumeric (A-Z,a-z,0-9), hyphen (-),\n\
-\          and period (.) characters.\n\
-\  --mac-package-name <name string>\n\
-\          Name of the application as it appears in the Menu Bar\n\
-\          This can be different from the application name.\n\
-\          This name must be less than 16 characters long and be suitable for\n\
-\          displaying in the menu bar and the application Info window.\n\
-\          Defaults to the application name.\n\
-\  --mac-package-signing-prefix <prefix string>\n\
-\          When signing the application package, this value is prefixed\n\
-\          to all components that need to be signed that don't have\n\
-\          an existing package identifier.\n\
-\  --mac-sign\n\
-\          Request that the package be signed\n\
-\  --mac-signing-keychain <file path>\n\
-\          Path of the keychain to search for the signing identity\n\
-\          (absolute path or relative to the current directory).\n\
-\          If not specified, the standard keychains are used.\n\
-\  --mac-signing-key-user-name <team name>\n\
-\          Team name portion in Apple signing identities' names.\n\
-\          For example "Developer ID Application: "\n\
-
-MSG_Help_linux_install=\
-\  --linux-package-name <package name>\n\
-\          Name for Linux package, defaults to the application name\n\
-\  --linux-deb-maintainer <email address>\n\
-\          Maintainer for .deb package\n\
-\  --linux-menu-group <menu-group-name>\n\
-\          Menu group this application is placed in\n\
-\  --linux-package-deps\n\
-\          Required packages or capabilities for the application\n\
-\  --linux-rpm-license-type <type string>\n\
-\          Type of the license ("License: <value>" of the RPM .spec)\n\
-\  --linux-app-release <release value>\n\
-\          Release value of the RPM <name>.spec file or \n\
-\          Debian revision value of the DEB control file.\n\
-\  --linux-app-category <category value>\n\
-\          Group value of the RPM <name>.spec file or \n\
-\          Section value of DEB control file.\n\
-\  --linux-shortcut\n\
-\          Creates a shortcut for the application\n\
-
-MSG_Help_mac_linux_install_dir=\
-\Absolute path of the installation directory of the application\n\
-
-MSG_Help_default_install_dir=\
-\Absolute path of the installation directory of the application on OS X\n\
-\          or Linux. Relative sub-path of the installation location of\n\
-\          the application such as "Program Files" or "AppData" on Windows.\n\
-
-MSG_Help_no_args=Usage: jpackage <mode> <options>\n\
-\Use jpackage --help (or -h) for a list of possible options\
-
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-param.copyright.default=Copyright (C) {0,date,YYYY}
-param.description.default=None
-param.vendor.default=Unknown
-
-warning.experimental=WARNING: Using experimental tool jpackage
-message.using-default-resource=Using default package resource {0} {1} (add {2} to the resource-dir to customize).
-message.no-default-resource=no default package resource {0} {1} (add {2} to the resource-dir to customize).
-message.using-custom-resource-from-file=Using custom package resource {0} (loaded from file {1}).
-message.using-custom-resource=Using custom package resource {0} (loaded from {1}).
-message.creating-app-bundle=Creating app package: {0} in {1}
-message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists
-message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
-message.runtime-image-dir-does-not-exist=Specified runtime image directory {0}: {1} does not exists
-message.runtime-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
-message.debug-working-directory=Kept working directory for debug: {0}
-message.bundle-created=Succeeded in building {0} package
-message.module-version=Using version "{0}" from module "{1}" as application version
-message.module-class=Using class "{0}" from module "{1}" as application main class
-
-error.cannot-create-output-dir=Destination directory {0} cannot be created
-error.cannot-write-to-output-dir=Destination directory {0} is not writable
-error.root-exists=Error: Application destination directory {0} already exists
-error.no-main-class-with-main-jar=A main class was not specified nor was one found in the jar {0}
-error.no-main-class-with-main-jar.advice=Specify a main class or ensure that the jar {0} specifies one in the manifest
-error.no-main-class=A main class was not specified nor was one found in the supplied application resources
-error.no-main-class.advice=Please specify a application class or ensure that the appResources has a jar containing one in the manifest
-error.main-jar-does-not-exist=The configured main jar does not exist {0} in the input directory
-error.main-jar-does-not-exist.advice=The main jar must be specified relative to the input directory (not an absolute path), and must exist within that directory
-
-error.tool-not-found=Can not find {0}. Reason: {1}
-error.tool-not-found.advice=Please install {0}
-error.tool-old-version=Can not find {0} {1} or newer
-error.tool-old-version.advice=Please install {0} {1} or newer
-error.jlink.failed=jlink failed with: {0}
-
-warning.module.does.not.exist=Module [{0}] does not exist
-warning.no.jdk.modules.found=Warning: No JDK Modules found
-
-MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
-MSG_BundlerConfigException=Bundler {0} skipped because of a configuration problem: {1} \n\
-Advice to fix: {2}
-MSG_BundlerConfigExceptionNoAdvice=Bundler {0} skipped because of a configuration problem: {1}
-MSG_BundlerRuntimeException=Bundler {0} failed because of {1}
-MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
-
-ERR_NoMainClass=Error: Main application class is missing
-ERR_UnsupportedOption=Error: Option [{0}] is not valid on this platform
-ERR_InvalidTypeOption=Error: Option [{0}] is not valid with type [{1}]
-ERR_NoInstallerEntryPoint=Error: Option [{0}] is not valid without --module or --main-jar entry point option
-
-ERR_MissingArgument=Error: Missing argument: {0}
-ERR_MissingAppResources=Error: No application jars found
-ERR_AppImageNotExist=Error: App image directory "{0}" does not exist
-ERR_NoAddLauncherName=Error: --add-launcher option requires a name and a file path (--add-launcher <name>=<file path>)
-ERR_NoUniqueName=Error: --add-launcher <name>=<file path> requires a unique name
-ERR_NoJreInstallerName=Error: Jre Installers require a name parameter
-ERR_InvalidAppName=Error: Invalid Application name: {0}
-ERR_InvalidSLName=Error: Invalid Add Launcher name: {0}
-ERR_LicenseFileNotExit=Error: Specified license file does not exist
-ERR_BuildRootInvalid=Error: temp ({0}) must be non-existant or empty directory
-ERR_InvalidOption=Error: Invalid Option: [{0}]
-ERR_InvalidInstallerType=Error: Invalid or unsupported type: [{0}]
-ERR_BothMainJarAndModule=Error: Cannot have both --main-jar and --module Options
-ERR_NoEntryPoint=Error: creating application image requires --main-jar or --module Option
-ERR_InputNotDirectory=Error: Input directory specified is not a directory: {0}
-ERR_CannotReadInputDir=Error: No permission to read from input directory: {0}
-ERR_CannotParseOptions=Error: Processing @filename option: {0}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-param.copyright.default=Copyright (C) {0,date,YYYY}
-param.description.default=None
-param.vendor.default=Unknown
-
-warning.experimental=WARNING: Using experimental tool jpackage
-message.using-default-resource=Using default package resource {0} {1} (add {2} to the resource-dir to customize).
-message.no-default-resource=no default package resource {0} {1} (add {2} to the resource-dir to customize).
-message.using-custom-resource-from-file=Using custom package resource {0} (loaded from file {1}).
-message.using-custom-resource=Using custom package resource {0} (loaded from {1}).
-message.creating-app-bundle=Creating app package: {0} in {1}
-message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists
-message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
-message.runtime-image-dir-does-not-exist=Specified runtime image directory {0}: {1} does not exists
-message.runtime-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
-message.debug-working-directory=Kept working directory for debug: {0}
-message.bundle-created=Succeeded in building {0} package
-message.module-version=Using version "{0}" from module "{1}" as application version
-message.module-class=Using class "{0}" from module "{1}" as application main class
-
-error.cannot-create-output-dir=Destination directory {0} cannot be created
-error.cannot-write-to-output-dir=Destination directory {0} is not writable
-error.root-exists=Error: Application destination directory {0} already exists
-error.no-main-class-with-main-jar=A main class was not specified nor was one found in the jar {0}
-error.no-main-class-with-main-jar.advice=Specify a main class or ensure that the jar {0} specifies one in the manifest
-error.no-main-class=A main class was not specified nor was one found in the supplied application resources
-error.no-main-class.advice=Please specify a application class or ensure that the appResources has a jar containing one in the manifest
-error.main-jar-does-not-exist=The configured main jar does not exist {0} in the input directory
-error.main-jar-does-not-exist.advice=The main jar must be specified relative to the input directory (not an absolute path), and must exist within that directory
-
-error.tool-not-found=Can not find {0}. Reason: {1}
-error.tool-not-found.advice=Please install {0}
-error.tool-old-version=Can not find {0} {1} or newer
-error.tool-old-version.advice=Please install {0} {1} or newer
-error.jlink.failed=jlink failed with: {0}
-
-warning.module.does.not.exist=Module [{0}] does not exist
-warning.no.jdk.modules.found=Warning: No JDK Modules found
-
-MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
-MSG_BundlerConfigException=Bundler {0} skipped because of a configuration problem: {1} \n\
-Advice to fix: {2}
-MSG_BundlerConfigExceptionNoAdvice=Bundler {0} skipped because of a configuration problem: {1}
-MSG_BundlerRuntimeException=Bundler {0} failed because of {1}
-MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
-
-ERR_NoMainClass=Error: Main application class is missing
-ERR_UnsupportedOption=Error: Option [{0}] is not valid on this platform
-ERR_InvalidTypeOption=Error: Option [{0}] is not valid with type [{1}]
-ERR_NoInstallerEntryPoint=Error: Option [{0}] is not valid without --module or --main-jar entry point option
-
-ERR_MissingArgument=Error: Missing argument: {0}
-ERR_MissingAppResources=Error: No application jars found
-ERR_AppImageNotExist=Error: App image directory "{0}" does not exist
-ERR_NoAddLauncherName=Error: --add-launcher option requires a name and a file path (--add-launcher <name>=<file path>)
-ERR_NoUniqueName=Error: --add-launcher <name>=<file path> requires a unique name
-ERR_NoJreInstallerName=Error: Jre Installers require a name parameter
-ERR_InvalidAppName=Error: Invalid Application name: {0}
-ERR_InvalidSLName=Error: Invalid Add Launcher name: {0}
-ERR_LicenseFileNotExit=Error: Specified license file does not exist
-ERR_BuildRootInvalid=Error: temp ({0}) must be non-existant or empty directory
-ERR_InvalidOption=Error: Invalid Option: [{0}]
-ERR_InvalidInstallerType=Error: Invalid or unsupported type: [{0}]
-ERR_BothMainJarAndModule=Error: Cannot have both --main-jar and --module Options
-ERR_NoEntryPoint=Error: creating application image requires --main-jar or --module Option
-ERR_InputNotDirectory=Error: Input directory specified is not a directory: {0}
-ERR_CannotReadInputDir=Error: No permission to read from input directory: {0}
-ERR_CannotParseOptions=Error: Processing @filename option: {0}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-param.copyright.default=Copyright (C) {0,date,YYYY}
-param.description.default=None
-param.vendor.default=Unknown
-
-warning.experimental=WARNING: Using experimental tool jpackage
-message.using-default-resource=Using default package resource {0} {1} (add {2} to the resource-dir to customize).
-message.no-default-resource=no default package resource {0} {1} (add {2} to the resource-dir to customize).
-message.using-custom-resource-from-file=Using custom package resource {0} (loaded from file {1}).
-message.using-custom-resource=Using custom package resource {0} (loaded from {1}).
-message.creating-app-bundle=Creating app package: {0} in {1}
-message.app-image-dir-does-not-exist=Specified application image directory {0}: {1} does not exists
-message.app-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
-message.runtime-image-dir-does-not-exist=Specified runtime image directory {0}: {1} does not exists
-message.runtime-image-dir-does-not-exist.advice=Confirm that the value for {0} exists
-message.debug-working-directory=Kept working directory for debug: {0}
-message.bundle-created=Succeeded in building {0} package
-message.module-version=Using version "{0}" from module "{1}" as application version
-message.module-class=Using class "{0}" from module "{1}" as application main class
-
-error.cannot-create-output-dir=Destination directory {0} cannot be created
-error.cannot-write-to-output-dir=Destination directory {0} is not writable
-error.root-exists=Error: Application destination directory {0} already exists
-error.no-main-class-with-main-jar=A main class was not specified nor was one found in the jar {0}
-error.no-main-class-with-main-jar.advice=Specify a main class or ensure that the jar {0} specifies one in the manifest
-error.no-main-class=A main class was not specified nor was one found in the supplied application resources
-error.no-main-class.advice=Please specify a application class or ensure that the appResources has a jar containing one in the manifest
-error.main-jar-does-not-exist=The configured main jar does not exist {0} in the input directory
-error.main-jar-does-not-exist.advice=The main jar must be specified relative to the input directory (not an absolute path), and must exist within that directory
-
-error.tool-not-found=Can not find {0}. Reason: {1}
-error.tool-not-found.advice=Please install {0}
-error.tool-old-version=Can not find {0} {1} or newer
-error.tool-old-version.advice=Please install {0} {1} or newer
-error.jlink.failed=jlink failed with: {0}
-
-warning.module.does.not.exist=Module [{0}] does not exist
-warning.no.jdk.modules.found=Warning: No JDK Modules found
-
-MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
-MSG_BundlerConfigException=Bundler {0} skipped because of a configuration problem: {1} \n\
-Advice to fix: {2}
-MSG_BundlerConfigExceptionNoAdvice=Bundler {0} skipped because of a configuration problem: {1}
-MSG_BundlerRuntimeException=Bundler {0} failed because of {1}
-MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a package
-
-ERR_NoMainClass=Error: Main application class is missing
-ERR_UnsupportedOption=Error: Option [{0}] is not valid on this platform
-ERR_InvalidTypeOption=Error: Option [{0}] is not valid with type [{1}]
-ERR_NoInstallerEntryPoint=Error: Option [{0}] is not valid without --module or --main-jar entry point option
-
-ERR_MissingArgument=Error: Missing argument: {0}
-ERR_MissingAppResources=Error: No application jars found
-ERR_AppImageNotExist=Error: App image directory "{0}" does not exist
-ERR_NoAddLauncherName=Error: --add-launcher option requires a name and a file path (--add-launcher <name>=<file path>)
-ERR_NoUniqueName=Error: --add-launcher <name>=<file path> requires a unique name
-ERR_NoJreInstallerName=Error: Jre Installers require a name parameter
-ERR_InvalidAppName=Error: Invalid Application name: {0}
-ERR_InvalidSLName=Error: Invalid Add Launcher name: {0}
-ERR_LicenseFileNotExit=Error: Specified license file does not exist
-ERR_BuildRootInvalid=Error: temp ({0}) must be non-existant or empty directory
-ERR_InvalidOption=Error: Invalid Option: [{0}]
-ERR_InvalidInstallerType=Error: Invalid or unsupported type: [{0}]
-ERR_BothMainJarAndModule=Error: Cannot have both --main-jar and --module Options
-ERR_NoEntryPoint=Error: creating application image requires --main-jar or --module Option
-ERR_InputNotDirectory=Error: Input directory specified is not a directory: {0}
-ERR_CannotReadInputDir=Error: No permission to read from input directory: {0}
-ERR_CannotParseOptions=Error: Processing @filename option: {0}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/ResourceLocator.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2011, 2019, 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.resources;
-
-/*
- * ResourceLocator
- *     This empty class is the only class in this package. Otherwise the
- * package consists only of resources. ResourceLocator is needed in order
- * to call getResourceAsStream() to get those resources.
- */
-
-public class ResourceLocator {
-    public ResourceLocator() {
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/main/CommandLine.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 1999, 2018, 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.main;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.File;
-import java.io.Reader;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * This file was originally a copy of CommandLine.java in
- * com.sun.tools.javac.main.
- * It should track changes made to that file.
- */
-
-/**
- * Various utility methods for processing Java tool command line arguments.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- */
-class CommandLine {
-    /**
-     * Process Win32-style command files for the specified command line
-     * arguments and return the resulting arguments. A command file argument
-     * is of the form '@file' where 'file' is the name of the file whose
-     * contents are to be parsed for additional arguments. The contents of
-     * the command file are parsed using StreamTokenizer and the original
-     * '@file' argument replaced with the resulting tokens. Recursive command
-     * files are not supported. The '@' character itself can be quoted with
-     * the sequence '@@'.
-     * @param args the arguments that may contain @files
-     * @return the arguments, with @files expanded
-     * @throws IOException if there is a problem reading any of the @files
-     */
-    public static String[] parse(String[] args) throws IOException {
-        List<String> newArgs = new ArrayList<>();
-        appendParsedCommandArgs(newArgs, Arrays.asList(args));
-        return newArgs.toArray(new String[newArgs.size()]);
-    }
-
-    private static void appendParsedCommandArgs(List<String> newArgs,
-            List<String> args) throws IOException {
-        for (String arg : args) {
-            if (arg.length() > 1 && arg.charAt(0) == '@') {
-                arg = arg.substring(1);
-                if (arg.charAt(0) == '@') {
-                    newArgs.add(arg);
-                } else {
-                    loadCmdFile(arg, newArgs);
-                }
-            } else {
-                newArgs.add(arg);
-            }
-        }
-    }
-
-    private static void loadCmdFile(String name, List<String> args)
-            throws IOException {
-        if (!Files.isReadable(Path.of(name))) {
-            throw new FileNotFoundException(name);
-        }
-        try (Reader r = Files.newBufferedReader(Paths.get(name),
-                Charset.defaultCharset())) {
-            Tokenizer t = new Tokenizer(r);
-            String s;
-            while ((s = t.nextToken()) != null) {
-                args.add(s);
-            }
-        }
-    }
-
-    public static class Tokenizer {
-        private final Reader in;
-        private int ch;
-
-        public Tokenizer(Reader in) throws IOException {
-            this.in = in;
-            ch = in.read();
-        }
-
-        public String nextToken() throws IOException {
-            skipWhite();
-            if (ch == -1) {
-                return null;
-            }
-
-            StringBuilder sb = new StringBuilder();
-            char quoteChar = 0;
-
-            while (ch != -1) {
-                switch (ch) {
-                    case ' ':
-                    case '\t':
-                    case '\f':
-                        if (quoteChar == 0) {
-                            return sb.toString();
-                        }
-                        sb.append((char) ch);
-                        break;
-
-                    case '\n':
-                    case '\r':
-                        return sb.toString();
-
-                    case '\'':
-                    case '"':
-                        if (quoteChar == 0) {
-                            quoteChar = (char) ch;
-                        } else if (quoteChar == ch) {
-                            quoteChar = 0;
-                        } else {
-                            sb.append((char) ch);
-                        }
-                        break;
-
-                    case '\\':
-                        if (quoteChar != 0) {
-                            ch = in.read();
-                            switch (ch) {
-                                case '\n':
-                                case '\r':
-                                    while (ch == ' ' || ch == '\n'
-                                            || ch == '\r' || ch == '\t'
-                                            || ch == '\f') {
-                                        ch = in.read();
-                                    }
-                                    continue;
-
-                                case 'n':
-                                    ch = '\n';
-                                    break;
-                                case 'r':
-                                    ch = '\r';
-                                    break;
-                                case 't':
-                                    ch = '\t';
-                                    break;
-                                case 'f':
-                                    ch = '\f';
-                                    break;
-                            }
-                        }
-                        sb.append((char) ch);
-                        break;
-
-                    default:
-                        sb.append((char) ch);
-                }
-
-                ch = in.read();
-            }
-
-            return sb.toString();
-        }
-
-        void skipWhite() throws IOException {
-            while (ch != -1) {
-                switch (ch) {
-                    case ' ':
-                    case '\t':
-                    case '\n':
-                    case '\r':
-                    case '\f':
-                        break;
-
-                    case '#':
-                        ch = in.read();
-                        while (ch != '\n' && ch != '\r' && ch != -1) {
-                            ch = in.read();
-                        }
-                        break;
-
-                    default:
-                        return;
-                }
-
-                ch = in.read();
-            }
-        }
-    }
-}
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/main/Main.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2011, 2019, 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
- * 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.main;
-
-import jdk.jpackage.internal.Arguments;
-import jdk.jpackage.internal.Log;
-import jdk.jpackage.internal.CLIHelp;
-import java.io.PrintWriter;
-import java.util.ResourceBundle;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.text.MessageFormat;
-
-public class Main {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.MainResources");
-
-    /**
-     * main(String... args)
-     * This is the entry point for the jpackage tool.
-     *
-     * @param args command line arguments
-     */
-    public static void main(String... args) throws Exception {
-        // Create logger with default system.out and system.err
-        Log.setLogger(null);
-
-        int status = new jdk.jpackage.main.Main().execute(args);
-        System.exit(status);
-    }
-
-    /**
-     * execute() - this is the entry point for the ToolProvider API.
-     *
-     * @param out output stream
-     * @param err error output stream
-     * @param args command line arguments
-     * @return an exit code. 0 means success, non-zero means an error occurred.
-     */
-    public int execute(PrintWriter out, PrintWriter err, String... args) {
-        // Create logger with provided streams
-        Log.Logger logger = new Log.Logger();
-        logger.setPrintWriter(out, err);
-        Log.setLogger(logger);
-
-        return execute(args);
-    }
-
-    private int execute(String... args) {
-        Log.info(I18N.getString("warning.experimental"));
-        try {
-            String[] newArgs;
-            try {
-                newArgs = CommandLine.parse(args);
-            } catch (FileNotFoundException fnfe) {
-                Log.error(MessageFormat.format(I18N.getString(
-                        "ERR_CannotParseOptions"), fnfe.getMessage()));
-                return 1;
-            } catch (IOException ioe) {
-                Log.error(ioe.getMessage());
-                return 1;
-            }
-
-            if (newArgs.length == 0) {
-                CLIHelp.showHelp(true);
-            } else if (hasHelp(newArgs)){
-                if (hasVersion(newArgs)) {
-                    Log.info(System.getProperty("java.version") + "\n");
-                }
-                CLIHelp.showHelp(false);
-            } else if (hasVersion(newArgs)) {
-                Log.info(System.getProperty("java.version"));
-            } else {
-                Arguments arguments = new Arguments(newArgs);
-                if (!arguments.processArguments()) {
-                    // processArguments() will log error message if failed.
-                    return 1;
-                }
-            }
-            return 0;
-        } finally {
-            Log.flush();
-        }
-    }
-
-    private boolean hasHelp(String[] args) {
-        for (String a : args) {
-            if ("--help".equals(a) || "-h".equals(a)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean hasVersion(String[] args) {
-        for (String a : args) {
-            if ("--version".equals(a)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}
--- a/src/jdk.jpackage/share/classes/module-info.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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.
- */
-
-/**
- * Defines the Java Packaging tool, jpackage.
- *
- * <p>jpackage is a tool for generating self-contained application bundles.
- *
- * <p> This module provides the equivalent of command-line access to <em>jpackage</em>
- * via the {@link java.util.spi.ToolProvider ToolProvider} SPI.
- * Instances of the tool can be obtained by calling
- * {@link java.util.spi.ToolProvider#findFirst ToolProvider.findFirst}
- * or the {@link java.util.ServiceLoader service loader} with the name
- * {@code "jpackage"}.
- *
- * @implNote The {@code jpackage} tool is not thread-safe. An application
- * should not call either of the
- * {@link java.util.spi.ToolProvider ToolProvider} {@code run} methods
- * concurrently, even with separate {@code "jpackage"} {@code ToolProvider}
- * instances, or undefined behavior may result.
- * <p></p>
- *
- * @moduleGraph
- * @since 14
- */
-
-module jdk.jpackage {
-    requires jdk.jlink;
-
-    requires java.desktop;
-
-    uses jdk.jpackage.internal.Bundler;
-    uses jdk.jpackage.internal.Bundlers;
-
-    provides jdk.jpackage.internal.Bundlers with
-        jdk.jpackage.internal.BasicBundlers;
-
-    provides java.util.spi.ToolProvider
-        with jdk.jpackage.internal.JPackageToolProvider;
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/FileAttributes.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef FILEATTRIBUTES_H
-#define FILEATTRIBUTES_H
-
-#include "Platform.h"
-#include "PlatformString.h"
-#include "FileAttribute.h"
-
-#include <vector>
-
-class FileAttributes {
-private:
-    TString FFileName;
-    bool FFollowLink;
-    std::vector<FileAttribute> FAttributes;
-
-    bool WriteAttributes();
-    bool ReadAttributes();
-    bool Valid(const FileAttribute Value);
-
-public:
-    FileAttributes(const TString FileName, bool FollowLink = true);
-
-    void Append(const FileAttribute Value);
-    bool Contains(const FileAttribute Value);
-    void Remove(const FileAttribute Value);
-};
-
-#endif // FILEATTRIBUTES_H
-
--- a/src/jdk.jpackage/share/native/libapplauncher/FilePath.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef FILEPATH_H
-#define FILEPATH_H
-
-#include "Platform.h"
-#include "PlatformString.h"
-#include "FileAttribute.h"
-
-#include <vector>
-
-class FileAttributes {
-private:
-    TString FFileName;
-    bool FFollowLink;
-    std::vector<FileAttribute> FAttributes;
-
-    bool WriteAttributes();
-    bool ReadAttributes();
-    bool Valid(const FileAttribute Value);
-
-public:
-    FileAttributes(const TString FileName, bool FollowLink = true);
-
-    void Append(const FileAttribute Value);
-    bool Contains(const FileAttribute Value);
-    void Remove(const FileAttribute Value);
-};
-
-class FilePath {
-private:
-    FilePath(void) {}
-    ~FilePath(void) {}
-
-public:
-    static bool FileExists(const TString FileName);
-    static bool DirectoryExists(const TString DirectoryName);
-
-    static bool DeleteFile(const TString FileName);
-    static bool DeleteDirectory(const TString DirectoryName);
-
-    static TString ExtractFilePath(TString Path);
-    static TString ExtractFileExt(TString Path);
-    static TString ExtractFileName(TString Path);
-    static TString ChangeFileExt(TString Path, TString Extension);
-
-    static TString IncludeTrailingSeparator(const TString value);
-    static TString IncludeTrailingSeparator(const char* value);
-    static TString IncludeTrailingSeparator(const wchar_t* value);
-    static TString FixPathForPlatform(TString Path);
-    static TString FixPathSeparatorForPlatform(TString Path);
-    static TString PathSeparator();
-
-    static bool CreateDirectory(TString Path, bool ownerOnly);
-    static void ChangePermissions(TString FileName, bool ownerOnly);
-};
-
-#endif //FILEPATH_H
--- a/src/jdk.jpackage/share/native/libapplauncher/Helpers.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "Helpers.h"
-#include "PlatformString.h"
-#include "PropertyFile.h"
-
-
-bool Helpers::SplitOptionIntoNameValue(
-        TString option, TString& Name, TString& Value) {
-    bool hasValue = false;
-    Name = _T("");
-    Value = _T("");
-    unsigned int index = 0;
-
-    for (; index < option.length(); index++) {
-        TCHAR c = option[index];
-
-        switch (c) {
-            case '=': {
-                index++;
-                hasValue = true;
-                break;
-            }
-
-            case '\\': {
-                if (index + 1 < option.length()) {
-                    c = option[index + 1];
-
-                    switch (c) {
-                        case '\\': {
-                            index++;
-                            Name += '\\';
-                            break;
-                        }
-
-                        case '=': {
-                            index++;
-                            Name += '=';
-                            break;
-                        }
-                    }
-
-                }
-
-                continue;
-            }
-
-            default: {
-                Name += c;
-                continue;
-            }
-        }
-
-        break;
-    }
-
-    if (hasValue) {
-        Value = option.substr(index, index - option.length());
-    }
-
-    return (option.length() > 0);
-}
-
-
-TString Helpers::ReplaceString(TString subject, const TString& search,
-                            const TString& replace) {
-    size_t pos = 0;
-    while((pos = subject.find(search, pos)) != TString::npos) {
-            subject.replace(pos, search.length(), replace);
-            pos += replace.length();
-    }
-    return subject;
-}
-
-TString Helpers::ConvertIdToFilePath(TString Value) {
-    TString search;
-    search = '.';
-    TString replace;
-    replace = '/';
-    TString result = ReplaceString(Value, search, replace);
-    return result;
-}
-
-TString Helpers::ConvertIdToJavaPath(TString Value) {
-    TString search;
-    search = '.';
-    TString replace;
-    replace = '/';
-    TString result = ReplaceString(Value, search, replace);
-    search = '\\';
-    result = ReplaceString(result, search, replace);
-    return result;
-}
-
-TString Helpers::ConvertJavaPathToId(TString Value) {
-    TString search;
-    search = '/';
-    TString replace;
-    replace = '.';
-    TString result = ReplaceString(Value, search, replace);
-    return result;
-}
-
-OrderedMap<TString, TString>
-        Helpers::GetJavaOptionsFromConfig(IPropertyContainer* config) {
-    OrderedMap<TString, TString> result;
-
-    for (unsigned int index = 0; index < config->GetCount(); index++) {
-        TString argname =
-                TString(_T("jvmarg.")) + PlatformString(index + 1).toString();
-        TString argvalue;
-
-        if (config->GetValue(argname, argvalue) == false) {
-            break;
-        }
-        else if (argvalue.empty() == false) {
-            TString name;
-            TString value;
-            if (Helpers::SplitOptionIntoNameValue(argvalue, name, value)) {
-                result.Append(name, value);
-            }
-        }
-    }
-
-    return result;
-}
-
-std::list<TString> Helpers::GetArgsFromConfig(IPropertyContainer* config) {
-    std::list<TString> result;
-
-    for (unsigned int index = 0; index < config->GetCount(); index++) {
-        TString argname = TString(_T("arg."))
-                + PlatformString(index + 1).toString();
-        TString argvalue;
-
-        if (config->GetValue(argname, argvalue) == false) {
-            break;
-        }
-        else if (argvalue.empty() == false) {
-            result.push_back((argvalue));
-        }
-    }
-
-    return result;
-}
-
-std::list<TString>
-        Helpers::MapToNameValueList(OrderedMap<TString, TString> Map) {
-    std::list<TString> result;
-    std::vector<TString> keys = Map.GetKeys();
-
-    for (OrderedMap<TString, TString>::const_iterator iterator = Map.begin();
-            iterator != Map.end(); iterator++) {
-       JPPair<TString, TString> *item = *iterator;
-       TString key = item->first;
-       TString value = item->second;
-
-       if (value.length() == 0) {
-           result.push_back(key);
-       } else {
-           result.push_back(key + _T('=') + value);
-        }
-    }
-
-    return result;
-}
-
-TString Helpers::NameValueToString(TString name, TString value) {
-    TString result;
-
-    if (value.empty() == true) {
-        result = name;
-    }
-    else {
-        result = name + TString(_T("=")) + value;
-    }
-
-    return result;
-}
-
-std::list<TString> Helpers::StringToArray(TString Value) {
-    std::list<TString> result;
-    TString line;
-
-    for (unsigned int index = 0; index < Value.length(); index++) {
-        TCHAR c = Value[index];
-
-        switch (c) {
-            case '\n': {
-                result.push_back(line);
-                line = _T("");
-                break;
-            }
-
-            case '\r': {
-                result.push_back(line);
-                line = _T("");
-
-                if (Value[index + 1] == '\n')
-                    index++;
-
-                break;
-            }
-
-            default: {
-                line += c;
-            }
-        }
-    }
-
-    // The buffer may not have ended with a Carriage Return/Line Feed.
-    if (line.length() > 0) {
-        result.push_back(line);
-    }
-
-    return result;
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/Helpers.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef HELPERS_H
-#define HELPERS_H
-
-#include "Platform.h"
-#include "OrderedMap.h"
-#include "IniFile.h"
-
-
-class Helpers {
-private:
-    Helpers(void) {}
-    ~Helpers(void) {}
-
-public:
-    // Supports two formats for option:
-    // Example 1:
-    // foo=bar
-    //
-    // Example 2:
-    // <name=foo=, value=goo>
-    static bool SplitOptionIntoNameValue(TString option,
-            TString& Name, TString& Value);
-    static TString ReplaceString(TString subject, const TString& search,
-            const TString& replace);
-    static TString ConvertIdToFilePath(TString Value);
-    static TString ConvertIdToJavaPath(TString Value);
-    static TString ConvertJavaPathToId(TString Value);
-
-    static OrderedMap<TString, TString>
-            GetJavaOptionsFromConfig(IPropertyContainer* config);
-    static std::list<TString> GetArgsFromConfig(IPropertyContainer* config);
-
-    static std::list<TString>
-            MapToNameValueList(OrderedMap<TString, TString> Map);
-
-    static TString NameValueToString(TString name, TString value);
-
-    static std::list<TString> StringToArray(TString Value);
-};
-
-#endif // HELPERS_H
--- a/src/jdk.jpackage/share/native/libapplauncher/IniFile.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.
- */
-
-#include "IniFile.h"
-#include "Helpers.h"
-
-#include <string>
-
-
-IniFile::IniFile() : ISectionalPropertyContainer() {
-}
-
-IniFile::~IniFile() {
-    for (OrderedMap<TString, IniSectionData*>::iterator iterator =
-            FMap.begin(); iterator != FMap.end(); iterator++) {
-        JPPair<TString, IniSectionData*> *item = *iterator;
-        delete item->second;
-    }
-}
-
-bool IniFile::LoadFromFile(const TString FileName) {
-    bool result = false;
-    Platform& platform = Platform::GetInstance();
-
-    std::list<TString> contents = platform.LoadFromFile(FileName);
-
-    if (contents.empty() == false) {
-        bool found = false;
-
-        // Determine the if file is an INI file or property file.
-        // Assign FDefaultSection if it is
-        // an INI file. Otherwise FDefaultSection is NULL.
-        for (std::list<TString>::const_iterator iterator = contents.begin();
-                iterator != contents.end(); iterator++) {
-            TString line = *iterator;
-
-            if (line[0] == ';') {
-                // Semicolon is a comment so ignore the line.
-                continue;
-            }
-            else {
-                if (line[0] == '[') {
-                    found = true;
-                }
-
-                break;
-            }
-        }
-
-        if (found == true) {
-            TString sectionName;
-
-            for (std::list<TString>::const_iterator iterator = contents.begin();
-                    iterator != contents.end(); iterator++) {
-                TString line = *iterator;
-
-                if (line[0] == ';') {
-                    // Semicolon is a comment so ignore the line.
-                    continue;
-                }
-                else if (line[0] == '[' && line[line.length() - 1] == ']') {
-                    sectionName = line.substr(1, line.size() - 2);
-                }
-                else if (sectionName.empty() == false) {
-                    TString name;
-                    TString value;
-
-                    if (Helpers::SplitOptionIntoNameValue(
-                            line, name, value) == true) {
-                        Append(sectionName, name, value);
-                    }
-                }
-            }
-
-            result = true;
-        }
-    }
-
-    return result;
-}
-
-bool IniFile::SaveToFile(const TString FileName, bool ownerOnly) {
-    bool result = false;
-
-    std::list<TString> contents;
-    std::vector<TString> keys = FMap.GetKeys();
-
-    for (unsigned int index = 0; index < keys.size(); index++) {
-        TString name = keys[index];
-        IniSectionData *section;
-
-        if (FMap.GetValue(name, section) == true) {
-            contents.push_back(_T("[") + name + _T("]"));
-            std::list<TString> lines = section->GetLines();
-            contents.insert(contents.end(), lines.begin(), lines.end());
-            contents.push_back(_T(""));
-        }
-    }
-
-    Platform& platform = Platform::GetInstance();
-    platform.SaveToFile(FileName, contents, ownerOnly);
-    result = true;
-    return result;
-}
-
-void IniFile::Append(const TString SectionName,
-        const TString Key, TString Value) {
-    if (FMap.ContainsKey(SectionName) == true) {
-        IniSectionData* section;
-
-        if (FMap.GetValue(SectionName, section) == true && section != NULL) {
-            section->SetValue(Key, Value);
-        }
-    }
-    else {
-        IniSectionData *section = new IniSectionData();
-        section->SetValue(Key, Value);
-        FMap.Append(SectionName, section);
-    }
-}
-
-void IniFile::AppendSection(const TString SectionName,
-        OrderedMap<TString, TString> Values) {
-    if (FMap.ContainsKey(SectionName) == true) {
-        IniSectionData* section;
-
-        if (FMap.GetValue(SectionName, section) == true && section != NULL) {
-            section->Append(Values);
-        }
-    }
-    else {
-        IniSectionData *section = new IniSectionData(Values);
-        FMap.Append(SectionName, section);
-    }
-}
-
-bool IniFile::GetValue(const TString SectionName,
-        const TString Key, TString& Value) {
-    bool result = false;
-    IniSectionData* section;
-
-    if (FMap.GetValue(SectionName, section) == true && section != NULL) {
-        result = section->GetValue(Key, Value);
-    }
-
-    return result;
-}
-
-bool IniFile::SetValue(const TString SectionName,
-        const TString Key, TString Value) {
-    bool result = false;
-    IniSectionData* section;
-
-    if (FMap.GetValue(SectionName, section) && section != NULL) {
-        result = section->SetValue(Key, Value);
-    }
-    else {
-        Append(SectionName, Key, Value);
-    }
-
-
-    return result;
-}
-
-bool IniFile::GetSection(const TString SectionName,
-        OrderedMap<TString, TString> &Data) {
-    bool result = false;
-
-    if (FMap.ContainsKey(SectionName) == true) {
-        IniSectionData* section = NULL;
-
-        if (FMap.GetValue(SectionName, section) == true && section != NULL) {
-            OrderedMap<TString, TString> data = section->GetData();
-            Data.Append(data);
-            result = true;
-        }
-    }
-
-    return result;
-}
-
-bool IniFile::ContainsSection(const TString SectionName) {
-    return FMap.ContainsKey(SectionName);
-}
-
-//----------------------------------------------------------------------------
-
-IniSectionData::IniSectionData() {
-    FMap.SetAllowDuplicates(true);
-}
-
-IniSectionData::IniSectionData(OrderedMap<TString, TString> Values) {
-    FMap = Values;
-}
-
-std::vector<TString> IniSectionData::GetKeys() {
-    return FMap.GetKeys();
-}
-
-std::list<TString> IniSectionData::GetLines() {
-    std::list<TString> result;
-    std::vector<TString> keys = FMap.GetKeys();
-
-    for (unsigned int index = 0; index < keys.size(); index++) {
-        TString name = keys[index];
-        TString value;
-
-        if (FMap.GetValue(name, value) == true) {
-            name = Helpers::ReplaceString(name, _T("="), _T("\\="));
-            value = Helpers::ReplaceString(value, _T("="), _T("\\="));
-
-            TString line = name + _T('=') + value;
-            result.push_back(line);
-        }
-    }
-
-    return result;
-}
-
-OrderedMap<TString, TString> IniSectionData::GetData() {
-    OrderedMap<TString, TString> result = FMap;
-    return result;
-}
-
-bool IniSectionData::GetValue(const TString Key, TString& Value) {
-    return FMap.GetValue(Key, Value);
-}
-
-bool IniSectionData::SetValue(const TString Key, TString Value) {
-    return FMap.SetValue(Key, Value);
-}
-
-void IniSectionData::Append(OrderedMap<TString, TString> Values) {
-    FMap.Append(Values);
-}
-
-size_t IniSectionData::GetCount() {
-    return FMap.Count();
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/IniFile.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.
- */
-
-#ifndef INIFILE_H
-#define INIFILE_H
-
-#include "Platform.h"
-#include "OrderedMap.h"
-
-#include <map>
-
-
-class IniSectionData : public IPropertyContainer {
-private:
-    OrderedMap<TString, TString> FMap;
-
-public:
-    IniSectionData();
-    IniSectionData(OrderedMap<TString, TString> Values);
-
-    std::vector<TString> GetKeys();
-    std::list<TString> GetLines();
-    OrderedMap<TString, TString> GetData();
-
-    bool SetValue(const TString Key, TString Value);
-    void Append(OrderedMap<TString, TString> Values);
-
-    virtual bool GetValue(const TString Key, TString& Value);
-    virtual size_t GetCount();
-};
-
-
-class IniFile : public ISectionalPropertyContainer {
-private:
-    OrderedMap<TString, IniSectionData*> FMap;
-
-public:
-    IniFile();
-    virtual ~IniFile();
-
-    void internalTest();
-
-    bool LoadFromFile(const TString FileName);
-    bool SaveToFile(const TString FileName, bool ownerOnly = true);
-
-    void Append(const TString SectionName, const TString Key, TString Value);
-    void AppendSection(const TString SectionName,
-            OrderedMap<TString, TString> Values);
-    bool SetValue(const TString SectionName,
-            const TString Key, TString Value);
-
-    // ISectionalPropertyContainer
-    virtual bool GetSection(const TString SectionName,
-            OrderedMap<TString, TString> &Data);
-    virtual bool ContainsSection(const TString SectionName);
-    virtual bool GetValue(const TString SectionName,
-            const TString Key, TString& Value);
-};
-
-#endif // INIFILE_H
--- a/src/jdk.jpackage/share/native/libapplauncher/JavaVirtualMachine.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,318 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "JavaVirtualMachine.h"
-#include "Platform.h"
-#include "PlatformString.h"
-#include "FilePath.h"
-#include "Package.h"
-#include "Helpers.h"
-#include "Messages.h"
-#include "Macros.h"
-
-#include "jni.h"
-
-#include <map>
-#include <list>
-#include <sstream>
-
-
-bool RunVM() {
-    JavaVirtualMachine javavm;
-
-    bool result = javavm.StartJVM();
-
-    if (!result) {
-        Platform& platform = Platform::GetInstance();
-        platform.ShowMessage(_T("Failed to launch JVM\n"));
-    }
-
-    return result;
-}
-
-//----------------------------------------------------------------------------
-
-JavaOptions::JavaOptions(): FOptions(NULL) {
-}
-
-JavaOptions::~JavaOptions() {
-    if (FOptions != NULL) {
-        for (unsigned int index = 0; index < GetCount(); index++) {
-            delete[] FOptions[index].optionString;
-        }
-
-        delete[] FOptions;
-    }
-}
-
-void JavaOptions::AppendValue(const TString Key, TString Value, void* Extra) {
-    JavaOptionItem item;
-    item.name = Key;
-    item.value = Value;
-    item.extraInfo = Extra;
-    FItems.push_back(item);
-}
-
-void JavaOptions::AppendValue(const TString Key, TString Value) {
-    AppendValue(Key, Value, NULL);
-}
-
-void JavaOptions::AppendValue(const TString Key) {
-    AppendValue(Key, _T(""), NULL);
-}
-
-void JavaOptions::AppendValues(OrderedMap<TString, TString> Values) {
-    if (Values.GetAllowDuplicates()) {
-        for (int i = 0; i < (int)Values.Count(); i++) {
-            TString name, value;
-
-            bool bResult = Values.GetKey(i, name);
-            bResult &= Values.GetValue(i, value);
-
-            if (bResult) {
-                AppendValue(name, value);
-            }
-        }
-    } else { // In case we asked to add values from OrderedMap with allow
-        // duplicates set to false. Not used now, but should avoid possible
-        // bugs.
-        std::vector<TString> orderedKeys = Values.GetKeys();
-
-        for (std::vector<TString>::const_iterator iterator = orderedKeys.begin();
-            iterator != orderedKeys.end(); iterator++) {
-            TString name = *iterator;
-            TString value;
-
-            if (Values.GetValue(name, value) == true) {
-                AppendValue(name, value);
-            }
-        }
-    }
-}
-
-void JavaOptions::ReplaceValue(const TString Key, TString Value) {
-    for (std::list<JavaOptionItem>::iterator iterator = FItems.begin();
-        iterator != FItems.end(); iterator++) {
-
-        TString lkey = iterator->name;
-
-        if (lkey == Key) {
-            JavaOptionItem item = *iterator;
-            item.value = Value;
-            iterator = FItems.erase(iterator);
-            FItems.insert(iterator, item);
-            break;
-        }
-    }
-}
-
-std::list<TString> JavaOptions::ToList() {
-    std::list<TString> result;
-    Macros& macros = Macros::GetInstance();
-
-    for (std::list<JavaOptionItem>::const_iterator iterator = FItems.begin();
-        iterator != FItems.end(); iterator++) {
-        TString key = iterator->name;
-        TString value = iterator->value;
-        TString option = Helpers::NameValueToString(key, value);
-        option = macros.ExpandMacros(option);
-        result.push_back(option);
-    }
-
-    return result;
-}
-
-size_t JavaOptions::GetCount() {
-    return FItems.size();
-}
-
-//----------------------------------------------------------------------------
-
-JavaVirtualMachine::JavaVirtualMachine() {
-}
-
-JavaVirtualMachine::~JavaVirtualMachine(void) {
-}
-
-bool JavaVirtualMachine::StartJVM() {
-    Platform& platform = Platform::GetInstance();
-    Package& package = Package::GetInstance();
-
-    TString classpath = package.GetClassPath();
-    TString modulepath = package.GetModulePath();
-    JavaOptions options;
-
-    if (modulepath.empty() == false) {
-        options.AppendValue(_T("-Djava.module.path"), modulepath);
-    }
-
-    options.AppendValue(_T("-Djava.library.path"),
-            package.GetPackageAppDirectory() + FilePath::PathSeparator()
-            + package.GetPackageLauncherDirectory());
-    options.AppendValue(
-            _T("-Djava.launcher.path"), package.GetPackageLauncherDirectory());
-    options.AppendValues(package.GetJavaOptions());
-
-#ifdef DEBUG
-    if (package.Debugging() == dsJava) {
-        options.AppendValue(_T("-Xdebug"), _T(""));
-        options.AppendValue(
-                _T("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=localhost:5005"),
-                _T(""));
-        platform.ShowMessage(_T("localhost:5005"));
-    }
-#endif // DEBUG
-
-    TString maxHeapSizeOption;
-    TString minHeapSizeOption;
-
-
-    if (package.GetMemoryState() == PackageBootFields::msAuto) {
-        TPlatformNumber memorySize = package.GetMemorySize();
-        TString memory =
-                PlatformString((size_t)memorySize).toString() + _T("m");
-        maxHeapSizeOption = TString(_T("-Xmx")) + memory;
-        options.AppendValue(maxHeapSizeOption, _T(""));
-
-        if (memorySize > 256)
-            minHeapSizeOption = _T("-Xms256m");
-        else
-            minHeapSizeOption = _T("-Xms") + memory;
-
-        options.AppendValue(minHeapSizeOption, _T(""));
-    }
-
-    TString mainClassName = package.GetMainClassName();
-    TString mainModule = package.GetMainModule();
-
-    if (mainClassName.empty() == true && mainModule.empty() == true) {
-        Messages& messages = Messages::GetInstance();
-        platform.ShowMessage(messages.GetMessage(NO_MAIN_CLASS_SPECIFIED));
-        return false;
-    }
-
-    configureLibrary();
-
-    // Initialize the arguments to JLI_Launch()
-    //
-    // On Mac OS X JLI_Launch spawns a new thread that actually starts the JVM.
-    // This new thread simply re-runs main(argc, argv). Therefore we do not
-    // want to add new args if we are still in the original main thread so we
-    // will treat them as command line args provided by the user ...
-    // Only propagate original set of args first time.
-
-    options.AppendValue(_T("-classpath"));
-    options.AppendValue(classpath);
-
-    std::list<TString> vmargs;
-    vmargs.push_back(package.GetCommandName());
-
-    if (package.HasSplashScreen() == true) {
-        options.AppendValue(TString(_T("-splash:"))
-                + package.GetSplashScreenFileName(), _T(""));
-    }
-
-    if (mainModule.empty() == true) {
-        options.AppendValue(Helpers::ConvertJavaPathToId(mainClassName),
-                _T(""));
-    } else {
-        options.AppendValue(_T("-m"));
-        options.AppendValue(mainModule);
-    }
-
-    return launchVM(options, vmargs);
-}
-
-void JavaVirtualMachine::configureLibrary() {
-    Platform& platform = Platform::GetInstance();
-    Package& package = Package::GetInstance();
-    TString libName = package.GetJavaLibraryFileName();
-    platform.addPlatformDependencies(&javaLibrary);
-    javaLibrary.Load(libName);
-}
-
-bool JavaVirtualMachine::launchVM(JavaOptions& options,
-        std::list<TString>& vmargs) {
-    Platform& platform = Platform::GetInstance();
-    Package& package = Package::GetInstance();
-
-#ifdef MAC
-    // Mac adds a ProcessSerialNumber to args when launched from .app
-    // filter out the psn since they it's not expected in the app
-    if (platform.IsMainThread() == false) {
-        std::list<TString> loptions = options.ToList();
-        vmargs.splice(vmargs.end(), loptions,
-                loptions.begin(), loptions.end());
-    }
-#else
-    std::list<TString> loptions = options.ToList();
-    vmargs.splice(vmargs.end(), loptions, loptions.begin(), loptions.end());
-#endif
-
-    std::list<TString> largs = package.GetArgs();
-    vmargs.splice(vmargs.end(), largs, largs.begin(), largs.end());
-
-    size_t argc = vmargs.size();
-    DynamicBuffer<char*> argv(argc + 1);
-    if (argv.GetData() == NULL) {
-        return false;
-    }
-
-    unsigned int index = 0;
-    for (std::list<TString>::const_iterator iterator = vmargs.begin();
-        iterator != vmargs.end(); iterator++) {
-        TString item = *iterator;
-        std::string arg = PlatformString(item).toStdString();
-#ifdef DEBUG
-        printf("%i %s\n", index, arg.c_str());
-#endif // DEBUG
-        argv[index] = PlatformString::duplicate(arg.c_str());
-        index++;
-    }
-
-    argv[argc] = NULL;
-
-// On Mac we can only free the boot fields if the calling thread is
-// not the main thread.
-#ifdef MAC
-    if (platform.IsMainThread() == false) {
-        package.FreeBootFields();
-    }
-#else
-    package.FreeBootFields();
-#endif // MAC
-
-    if (javaLibrary.JavaVMCreate(argc, argv.GetData()) == true) {
-        return true;
-    }
-
-    for (index = 0; index < argc; index++) {
-        if (argv[index] != NULL) {
-            delete[] argv[index];
-        }
-    }
-
-    return false;
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/JavaVirtualMachine.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef JAVAVIRTUALMACHINE_H
-#define JAVAVIRTUALMACHINE_H
-
-
-#include "jni.h"
-#include "Platform.h"
-#include "Library.h"
-
-struct JavaOptionItem {
-    TString name;
-    TString value;
-    void* extraInfo;
-};
-
-class JavaOptions {
-private:
-    std::list<JavaOptionItem> FItems;
-    JavaVMOption* FOptions;
-
-public:
-    JavaOptions();
-    ~JavaOptions();
-
-    void AppendValue(const TString Key, TString Value, void* Extra);
-    void AppendValue(const TString Key, TString Value);
-    void AppendValue(const TString Key);
-    void AppendValues(OrderedMap<TString, TString> Values);
-    void ReplaceValue(const TString Key, TString Value);
-    std::list<TString> ToList();
-    size_t GetCount();
-};
-
-class JavaVirtualMachine {
-private:
-    JavaLibrary javaLibrary;
-
-    void configureLibrary();
-    bool launchVM(JavaOptions& options, std::list<TString>& vmargs);
-public:
-    JavaVirtualMachine();
-    ~JavaVirtualMachine(void);
-
-    bool StartJVM();
-};
-
-bool RunVM();
-
-#endif // JAVAVIRTUALMACHINE_H
--- a/src/jdk.jpackage/share/native/libapplauncher/Library.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "Library.h"
-#include "Platform.h"
-#include "Messages.h"
-#include "PlatformString.h"
-
-#include <fstream>
-#include <locale>
-
-Library::Library() {
-    Initialize();
-}
-
-Library::Library(const TString &FileName) {
-    Initialize();
-    Load(FileName);
-}
-
-Library::~Library() {
-    Unload();
-}
-
-void Library::Initialize() {
-    FModule = NULL;
-    FDependentLibraryNames = NULL;
-    FDependenciesLibraries = NULL;
-}
-
-void Library::InitializeDependencies() {
-    if (FDependentLibraryNames == NULL) {
-        FDependentLibraryNames = new std::vector<TString>();
-    }
-
-    if (FDependenciesLibraries == NULL) {
-        FDependenciesLibraries = new std::vector<Library*>();
-    }
-}
-
-void Library::LoadDependencies() {
-    if (FDependentLibraryNames != NULL && FDependenciesLibraries != NULL) {
-        for (std::vector<TString>::const_iterator iterator =
-                FDependentLibraryNames->begin();
-                iterator != FDependentLibraryNames->end(); iterator++) {
-            Library* library = new Library();
-
-            if (library->Load(*iterator) == true) {
-                FDependenciesLibraries->push_back(library);
-            }
-        }
-
-        delete FDependentLibraryNames;
-        FDependentLibraryNames = NULL;
-    }
-}
-
-void Library::UnloadDependencies() {
-    if (FDependenciesLibraries != NULL) {
-        for (std::vector<Library*>::const_iterator iterator =
-                FDependenciesLibraries->begin();
-                iterator != FDependenciesLibraries->end(); iterator++) {
-            Library* library = *iterator;
-
-            if (library != NULL) {
-                library->Unload();
-                delete library;
-            }
-        }
-
-        delete FDependenciesLibraries;
-        FDependenciesLibraries = NULL;
-    }
-}
-
-Procedure Library::GetProcAddress(const std::string& MethodName) const {
-    Platform& platform = Platform::GetInstance();
-    return platform.GetProcAddress(FModule, MethodName);
-}
-
-bool Library::Load(const TString &FileName) {
-    bool result = true;
-
-    if (FModule == NULL) {
-        LoadDependencies();
-        Platform& platform = Platform::GetInstance();
-        FModule = platform.LoadLibrary(FileName);
-
-        if (FModule == NULL) {
-            Messages& messages = Messages::GetInstance();
-            platform.ShowMessage(messages.GetMessage(LIBRARY_NOT_FOUND),
-                    FileName);
-            result = false;
-        } else {
-            fname = PlatformString(FileName).toStdString();
-        }
-    }
-
-    return result;
-}
-
-bool Library::Unload() {
-    bool result = false;
-
-    if (FModule != NULL) {
-        Platform& platform = Platform::GetInstance();
-        platform.FreeLibrary(FModule);
-        FModule = NULL;
-        UnloadDependencies();
-        result = true;
-    }
-
-    return result;
-}
-
-void Library::AddDependency(const TString &FileName) {
-    InitializeDependencies();
-
-    if (FDependentLibraryNames != NULL) {
-        FDependentLibraryNames->push_back(FileName);
-    }
-}
-
-void Library::AddDependencies(const std::vector<TString> &Dependencies) {
-    if (Dependencies.size() > 0) {
-        InitializeDependencies();
-
-        if (FDependentLibraryNames != NULL) {
-            for (std::vector<TString>::const_iterator iterator =
-                    FDependentLibraryNames->begin();
-                    iterator != FDependentLibraryNames->end(); iterator++) {
-                TString fileName = *iterator;
-                AddDependency(fileName);
-            }
-        }
-    }
-}
-
-JavaLibrary::JavaLibrary() : Library(), FCreateProc(NULL) {
-}
-
-bool JavaLibrary::JavaVMCreate(size_t argc, char *argv[]) {
-    if (FCreateProc == NULL) {
-        FCreateProc = (JAVA_CREATE) GetProcAddress(LAUNCH_FUNC);
-    }
-
-    if (FCreateProc == NULL) {
-        Platform& platform = Platform::GetInstance();
-        Messages& messages = Messages::GetInstance();
-        platform.ShowMessage(
-                messages.GetMessage(FAILED_LOCATING_JVM_ENTRY_POINT));
-        return false;
-    }
-
-    return FCreateProc((int) argc, argv,
-            0, NULL,
-            0, NULL,
-            "",
-            "",
-            "java",
-            "java",
-            false,
-            false,
-            false,
-            0) == 0;
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/Library.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef LIBRARY_H
-#define LIBRARY_H
-
-#include "PlatformDefs.h"
-//#include "Platform.h"
-#include "OrderedMap.h"
-
-#include "jni.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <string>
-#include <map>
-#include <list>
-#include <vector>
-#include <fstream>
-
-using namespace std;
-
-// Private typedef for function pointer casting
-
-#if defined(_WIN32) && !defined(_WIN64)
-#define LAUNCH_FUNC "_JLI_Launch@56"
-#else
-#define LAUNCH_FUNC "JLI_Launch"
-#endif
-
-
-typedef int (JNICALL *JAVA_CREATE)(int argc, char ** argv,
-        int jargc, const char** jargv,
-        int appclassc, const char** appclassv,
-        const char* fullversion,
-        const char* dotversion,
-        const char* pname,
-        const char* lname,
-        jboolean javaargs,
-        jboolean cpwildcard,
-        jboolean javaw,
-        jint ergo);
-
-class Library {
-private:
-    std::vector<TString> *FDependentLibraryNames;
-    std::vector<Library*> *FDependenciesLibraries;
-    Module FModule;
-    std::string fname;
-
-    void Initialize();
-    void InitializeDependencies();
-    void LoadDependencies();
-    void UnloadDependencies();
-
-public:
-    void* GetProcAddress(const std::string& MethodName) const;
-
-public:
-    Library();
-    Library(const TString &FileName);
-    ~Library();
-
-    bool Load(const TString &FileName);
-    bool Unload();
-
-    const std::string& GetName() const {
-        return fname;
-    }
-
-    void AddDependency(const TString &FileName);
-    void AddDependencies(const std::vector<TString> &Dependencies);
-};
-
-class JavaLibrary : public Library {
-    JAVA_CREATE FCreateProc;
-    JavaLibrary(const TString &FileName);
-public:
-    JavaLibrary();
-    bool JavaVMCreate(size_t argc, char *argv[]);
-};
-
-#endif // LIBRARY_H
-
--- a/src/jdk.jpackage/share/native/libapplauncher/Macros.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "Macros.h"
-#include "Package.h"
-#include "Helpers.h"
-
-
-Macros::Macros(void) {
-}
-
-Macros::~Macros(void) {
-}
-
-void Macros::Initialize() {
-    Package& package = Package::GetInstance();
-    Macros& macros = Macros::GetInstance();
-
-    // Public macros.
-    macros.AddMacro(_T("$ROOTDIR"), package.GetPackageRootDirectory());
-    macros.AddMacro(_T("$APPDIR"), package.GetPackageAppDirectory());
-    macros.AddMacro(_T("$BINDIR"), package.GetPackageLauncherDirectory());
-}
-
-Macros& Macros::GetInstance() {
-    static Macros instance;
-    return instance;
-}
-
-TString Macros::ExpandMacros(TString Value) {
-    TString result = Value;
-
-    for (std::map<TString, TString>::iterator iterator = FData.begin();
-        iterator != FData.end();
-        iterator++) {
-
-        TString name = iterator->first;
-
-        if (Value.find(name) != TString::npos) {
-            TString lvalue = iterator->second;
-            result = Helpers::ReplaceString(Value, name, lvalue);
-            result = ExpandMacros(result);
-            break;
-        }
-    }
-
-    return result;
-}
-
-void Macros::AddMacro(TString Key, TString Value) {
-    FData.insert(std::map<TString, TString>::value_type(Key, Value));
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/Macros.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef MACROS_H
-#define MACROS_H
-
-#include "Platform.h"
-
-#include <map>
-
-
-class Macros {
-private:
-    std::map<TString, TString> FData;
-
-    Macros(void);
-
-public:
-    static Macros& GetInstance();
-    static void Initialize();
-    ~Macros(void);
-
-    TString ExpandMacros(TString Value);
-    void AddMacro(TString Key, TString Value);
-};
-
-#endif // MACROS_H
--- a/src/jdk.jpackage/share/native/libapplauncher/Messages.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "Messages.h"
-#include "Platform.h"
-#include "FilePath.h"
-#include "Helpers.h"
-#include "Macros.h"
-#include "JavaVirtualMachine.h"
-
-Messages::Messages(void) {
-    FMessages.SetReadOnly(false);
-    FMessages.SetValue(LIBRARY_NOT_FOUND, _T("Failed to find library."));
-    FMessages.SetValue(FAILED_CREATING_JVM, _T("Failed to create JVM"));
-    FMessages.SetValue(FAILED_LOCATING_JVM_ENTRY_POINT,
-            _T("Failed to locate JLI_Launch"));
-    FMessages.SetValue(NO_MAIN_CLASS_SPECIFIED, _T("No main class specified"));
-    FMessages.SetValue(METHOD_NOT_FOUND, _T("No method %s in class %s."));
-    FMessages.SetValue(CLASS_NOT_FOUND, _T("Class %s not found."));
-    FMessages.SetValue(ERROR_INVOKING_METHOD, _T("Error invoking method."));
-    FMessages.SetValue(APPCDS_CACHE_FILE_NOT_FOUND,
-            _T("Error: AppCDS cache does not exists:\n%s\n"));
-}
-
-Messages& Messages::GetInstance() {
-    static Messages instance;
-    // Guaranteed to be destroyed. Instantiated on first use.
-    return instance;
-}
-
-Messages::~Messages(void) {
-}
-
-TString Messages::GetMessage(const TString Key) {
-    TString result;
-    FMessages.GetValue(Key, result);
-    Macros& macros = Macros::GetInstance();
-    result = macros.ExpandMacros(result);
-    return result;
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/Messages.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef MESSAGES_H
-#define MESSAGES_H
-
-#include "PropertyFile.h"
-
-#define LIBRARY_NOT_FOUND _T("library.not.found")
-#define FAILED_CREATING_JVM _T("failed.creating.jvm")
-#define FAILED_LOCATING_JVM_ENTRY_POINT _T("failed.locating.jvm.entry.point")
-#define NO_MAIN_CLASS_SPECIFIED _T("no.main.class.specified")
-
-#define METHOD_NOT_FOUND _T("method.not.found")
-#define CLASS_NOT_FOUND _T("class.not.found")
-#define ERROR_INVOKING_METHOD _T("error.invoking.method")
-
-#define CONFIG_FILE_NOT_FOUND _T("config.file.not.found")
-
-#define BUNDLED_JVM_NOT_FOUND _T("bundled.jvm.not.found")
-
-#define APPCDS_CACHE_FILE_NOT_FOUND _T("appcds.cache.file.not.found")
-
-class Messages {
-private:
-    PropertyFile FMessages;
-
-    Messages(void);
-public:
-    static Messages& GetInstance();
-    ~Messages(void);
-
-    TString GetMessage(const TString Key);
-};
-
-#endif // MESSAGES_H
--- a/src/jdk.jpackage/share/native/libapplauncher/OrderedMap.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.
- */
-
-#ifndef ORDEREDMAP_H
-#define ORDEREDMAP_H
-
-#include <map>
-#include <vector>
-#include <assert.h>
-#include <stdexcept>
-
-#include <iostream>
-
-template <typename _T1, typename _T2>
-struct JPPair
-{
-    typedef _T1 first_type;
-    typedef _T2 second_type;
-
-    first_type first;
-    second_type second;
-
-    JPPair(first_type Value1, second_type Value2) {
-        first = Value1;
-        second = Value2;
-    }
-};
-
-
-template <typename TKey, typename TValue>
-class OrderedMap {
-public:
-    typedef TKey key_type;
-    typedef TValue mapped_type;
-    typedef JPPair<key_type, mapped_type> container_type;
-    typedef typename std::vector<container_type*>::iterator iterator;
-    typedef typename std::vector<container_type*>::const_iterator const_iterator;
-
-private:
-    typedef std::map<key_type, container_type*> map_type;
-    typedef std::vector<container_type*> list_type;
-
-    map_type FMap;
-    list_type FList;
-    bool FAllowDuplicates;
-
-    typename list_type::iterator FindListItem(const key_type Key) {
-        typename list_type::iterator result = FList.end();
-
-        for (typename list_type::iterator iterator =
-                FList.begin(); iterator != FList.end(); iterator++) {
-            container_type *item = *iterator;
-
-            if (item->first == Key) {
-                result = iterator;
-                break;
-            }
-        }
-
-        return result;
-    }
-
-public:
-    OrderedMap() {
-        FAllowDuplicates = false;
-    }
-
-    OrderedMap(const OrderedMap<key_type, mapped_type> &Value) {
-        Append(Value);
-        FAllowDuplicates = Value.GetAllowDuplicates();
-    }
-
-    ~OrderedMap() {
-        Clear();
-    }
-
-    void SetAllowDuplicates(bool Value) {
-        FAllowDuplicates = Value;
-    }
-
-    bool GetAllowDuplicates() const {
-        return FAllowDuplicates;
-    }
-
-    iterator begin() {
-        return FList.begin();
-    }
-
-    const_iterator begin() const {
-        return FList.begin();
-    }
-
-    iterator end() {
-        return FList.end();
-    }
-
-    const_iterator end() const {
-        return FList.end();
-    }
-
-    void Clear() {
-        for (typename list_type::iterator iterator =
-                FList.begin(); iterator != FList.end(); iterator++) {
-            container_type *item = *iterator;
-
-            if (item != NULL) {
-                delete item;
-                item = NULL;
-            }
-        }
-
-        FMap.clear();
-        FList.clear();
-    }
-
-    bool ContainsKey(key_type Key) {
-        bool result = false;
-
-        if (FMap.find(Key) != FMap.end()) {
-            result = true;
-        }
-
-        return result;
-    }
-
-    std::vector<key_type> GetKeys() {
-        std::vector<key_type> result;
-
-        for (typename list_type::const_iterator iterator = FList.begin();
-             iterator != FList.end(); iterator++) {
-            container_type *item = *iterator;
-            result.push_back(item->first);
-        }
-
-        return result;
-    }
-
-    void Assign(const OrderedMap<key_type, mapped_type> &Value) {
-        Clear();
-        Append(Value);
-    }
-
-    void Append(const OrderedMap<key_type, mapped_type> &Value) {
-        for (size_t index = 0; index < Value.FList.size(); index++) {
-            container_type *item = Value.FList[index];
-            Append(item->first, item->second);
-        }
-    }
-
-    void Append(key_type Key, mapped_type Value) {
-        container_type *item = new container_type(Key, Value);
-        FMap.insert(std::pair<key_type, container_type*>(Key, item));
-        FList.push_back(item);
-    }
-
-    bool RemoveByKey(key_type Key) {
-        bool result = false;
-        typename list_type::iterator iterator = FindListItem(Key);
-
-        if (iterator != FList.end()) {
-            FMap.erase(Key);
-            FList.erase(iterator);
-            result = true;
-        }
-
-        return result;
-    }
-
-    bool GetValue(key_type Key, mapped_type &Value) {
-        bool result = false;
-        container_type* item = FMap[Key];
-
-        if (item != NULL) {
-            Value = item->second;
-            result = true;
-        }
-
-        return result;
-    }
-
-    bool SetValue(key_type Key, mapped_type &Value) {
-        bool result = false;
-
-        if ((FAllowDuplicates == false) && (ContainsKey(Key) == true)) {
-            container_type *item = FMap[Key];
-
-            if (item != NULL) {
-                item->second = Value;
-                result = true;
-            }
-        }
-        else {
-            Append(Key, Value);
-            result = true;
-        }
-
-        return result;
-    }
-
-    bool GetKey(int index, key_type &Value) {
-        if (index < 0 || index >= (int)FList.size()) {
-            return false;
-        }
-        container_type *item = FList.at(index);
-        if (item != NULL) {
-            Value = item->first;
-            return true;
-        }
-
-        return false;
-    }
-
-    bool GetValue(int index, mapped_type &Value) {
-        if (index < 0 || index >= (int)FList.size()) {
-            return false;
-        }
-        container_type *item = FList.at(index);
-        if (item != NULL) {
-            Value = item->second;
-            return true;
-        }
-
-        return false;
-    }
-
-    mapped_type &operator[](key_type Key) {
-        container_type* item = FMap[Key];
-        assert(item != NULL);
-
-        if (item != NULL) {
-            return item->second;
-        }
-
-        throw std::invalid_argument("Key not found");
-    }
-
-    OrderedMap& operator= (OrderedMap &Value) {
-        Clear();
-        FAllowDuplicates = Value.GetAllowDuplicates();
-        Append(Value);
-        return *this;
-    }
-
-    size_t Count() {
-        return FList.size();
-    }
-};
-
-#endif // ORDEREDMAP_H
--- a/src/jdk.jpackage/share/native/libapplauncher/Package.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,557 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "Package.h"
-#include "Helpers.h"
-#include "Macros.h"
-#include "IniFile.h"
-
-#include <assert.h>
-
-
-Package::Package(void) {
-    FInitialized = false;
-    Initialize();
-}
-
-TPlatformNumber StringToPercentageOfNumber(TString Value,
-        TPlatformNumber Number) {
-    TPlatformNumber result = 0;
-    size_t percentage = atoi(PlatformString(Value.c_str()));
-
-    if (percentage > 0 && Number > 0) {
-        result = Number * percentage / 100;
-    }
-
-    return result;
-}
-
-void Package::Initialize() {
-    if (FInitialized == true) {
-        return;
-    }
-
-    Platform& platform = Platform::GetInstance();
-
-    FBootFields = new PackageBootFields();
-    FDebugging = dsNone;
-
-    // Allow duplicates for Java options, so we can have multiple --add-exports
-    // or similar args.
-    FBootFields->FJavaOptions.SetAllowDuplicates(true);
-    FBootFields->FPackageRootDirectory = platform.GetPackageRootDirectory();
-    FBootFields->FPackageAppDirectory = platform.GetPackageAppDirectory();
-    FBootFields->FPackageLauncherDirectory =
-            platform.GetPackageLauncherDirectory();
-    FBootFields->FAppDataDirectory = platform.GetAppDataDirectory();
-
-    std::map<TString, TString> keys = platform.GetKeys();
-
-    // Read from configure.cfg/Info.plist
-    AutoFreePtr<ISectionalPropertyContainer> config =
-            platform.GetConfigFile(platform.GetConfigFileName());
-
-    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-            keys[JPACKAGE_APP_DATA_DIR], FBootFields->FPackageAppDataDirectory);
-    FBootFields->FPackageAppDataDirectory =
-            FilePath::FixPathForPlatform(FBootFields->FPackageAppDataDirectory);
-
-    // Main JAR.
-    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-            keys[CONFIG_MAINJAR_KEY], FBootFields->FMainJar);
-    FBootFields->FMainJar = FilePath::FixPathForPlatform(FBootFields->FMainJar);
-
-    // Main Module.
-    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-            keys[CONFIG_MAINMODULE_KEY], FBootFields->FMainModule);
-
-    // Classpath.
-    // 1. If the provided class path contains main jar then only use
-    //    provided class path.
-    // 2. If class path provided by config file is empty then add main jar.
-    // 3. If main jar is not in provided class path then add it.
-    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-            keys[CONFIG_CLASSPATH_KEY], FBootFields->FClassPath);
-    FBootFields->FClassPath =
-            FilePath::FixPathSeparatorForPlatform(FBootFields->FClassPath);
-
-    if (FBootFields->FClassPath.empty() == true) {
-        FBootFields->FClassPath = GetMainJar();
-    } else if (FBootFields->FClassPath.find(GetMainJar()) == TString::npos) {
-        FBootFields->FClassPath = GetMainJar()
-                + FilePath::PathSeparator() + FBootFields->FClassPath;
-    }
-
-    // Modulepath.
-    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-            keys[CONFIG_MODULEPATH_KEY], FBootFields->FModulePath);
-    FBootFields->FModulePath =
-            FilePath::FixPathSeparatorForPlatform(FBootFields->FModulePath);
-
-    // Main Class.
-    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-            keys[CONFIG_MAINCLASSNAME_KEY], FBootFields->FMainClassName);
-
-    // Splash Screen.
-    if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-            keys[CONFIG_SPLASH_KEY],
-            FBootFields->FSplashScreenFileName) == true) {
-        FBootFields->FSplashScreenFileName =
-            FilePath::IncludeTrailingSeparator(GetPackageAppDirectory())
-            + FilePath::FixPathForPlatform(FBootFields->FSplashScreenFileName);
-
-        if (FilePath::FileExists(FBootFields->FSplashScreenFileName) == false) {
-            FBootFields->FSplashScreenFileName = _T("");
-        }
-    }
-
-    // Runtime.
-    config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-            keys[JAVA_RUNTIME_KEY], FBootFields->FJavaRuntimeDirectory);
-
-    // Read jvmargs.
-    PromoteAppCDSState(config);
-    ReadJavaOptions(config);
-
-    // Read args if none were passed in.
-    if (FBootFields->FArgs.size() == 0) {
-        OrderedMap<TString, TString> args;
-
-        if (config->GetSection(keys[CONFIG_SECTION_ARGOPTIONS], args) == true) {
-            FBootFields->FArgs = Helpers::MapToNameValueList(args);
-        }
-    }
-
-    // Auto Memory.
-    TString autoMemory;
-
-    if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-            keys[CONFIG_APP_MEMORY], autoMemory) == true) {
-        if (autoMemory == _T("auto") || autoMemory == _T("100%")) {
-            FBootFields->FMemoryState = PackageBootFields::msAuto;
-            FBootFields->FMemorySize = platform.GetMemorySize();
-        } else if (autoMemory.length() == 2 && isdigit(autoMemory[0]) &&
-                autoMemory[1] == '%') {
-            FBootFields->FMemoryState = PackageBootFields::msAuto;
-            FBootFields->FMemorySize =
-                    StringToPercentageOfNumber(autoMemory.substr(0, 1),
-                    platform.GetMemorySize());
-        } else if (autoMemory.length() == 3 && isdigit(autoMemory[0]) &&
-                isdigit(autoMemory[1]) && autoMemory[2] == '%') {
-            FBootFields->FMemoryState = PackageBootFields::msAuto;
-            FBootFields->FMemorySize =
-                    StringToPercentageOfNumber(autoMemory.substr(0, 2),
-                    platform.GetMemorySize());
-        } else {
-            FBootFields->FMemoryState = PackageBootFields::msManual;
-            FBootFields->FMemorySize = 0;
-        }
-    }
-
-    // Debug
-    TString debug;
-    if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-            keys[CONFIG_APP_DEBUG], debug) == true) {
-        FBootFields->FArgs.push_back(debug);
-    }
-}
-
-void Package::Clear() {
-    FreeBootFields();
-    FInitialized = false;
-}
-
-// This is the only location that the AppCDS state should be modified except
-// by command line arguments provided by the user.
-//
-// The state of AppCDS is as follows:
-//
-// -> cdsUninitialized
-//    -> cdsGenCache If -Xappcds:generatecache
-//    -> cdsDisabled If -Xappcds:off
-//    -> cdsEnabled If "AppCDSJavaOptions" section is present
-//    -> cdsAuto If "AppCDSJavaOptions" section is present and
-//               app.appcds.cache=auto
-//    -> cdsDisabled Default
-//
-void Package::PromoteAppCDSState(ISectionalPropertyContainer* Config) {
-    Platform& platform = Platform::GetInstance();
-    std::map<TString, TString> keys = platform.GetKeys();
-
-    // The AppCDS state can change at this point.
-    switch (platform.GetAppCDSState()) {
-        case cdsEnabled:
-        case cdsAuto:
-        case cdsDisabled:
-        case cdsGenCache: {
-            // Do nothing.
-            break;
-        }
-
-        case cdsUninitialized: {
-            if (Config->ContainsSection(
-                    keys[CONFIG_SECTION_APPCDSJAVAOPTIONS]) == true) {
-                // If the AppCDS section is present then enable AppCDS.
-                TString appCDSCacheValue;
-
-                // If running with AppCDS enabled, and the configuration has
-                // been setup so "auto" is enabled, then
-                // the launcher will attempt to generate the cache file
-                // automatically and run the application.
-                if (Config->GetValue(keys[CONFIG_SECTION_APPLICATION],
-                        _T("app.appcds.cache"), appCDSCacheValue) == true &&
-                    appCDSCacheValue == _T("auto")) {
-                    platform.SetAppCDSState(cdsAuto);
-                }
-                else {
-                    platform.SetAppCDSState(cdsEnabled);
-                }
-            } else {
-
-                platform.SetAppCDSState(cdsDisabled);
-            }
-        }
-    }
-}
-
-void Package::ReadJavaOptions(ISectionalPropertyContainer* Config) {
-    Platform& platform = Platform::GetInstance();
-    std::map<TString, TString> keys = platform.GetKeys();
-
-    // Evaluate based on the current AppCDS state.
-    switch (platform.GetAppCDSState()) {
-        case cdsUninitialized: {
-            throw Exception(_T("Internal Error"));
-        }
-
-        case cdsDisabled: {
-            Config->GetSection(keys[CONFIG_SECTION_JAVAOPTIONS],
-                    FBootFields->FJavaOptions);
-            break;
-        }
-
-        case cdsGenCache: {
-            Config->GetSection(keys[
-                    CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS],
-                    FBootFields->FJavaOptions);
-            break;
-        }
-
-        case cdsAuto:
-        case cdsEnabled: {
-            if (Config->GetValue(keys[CONFIG_SECTION_APPCDSJAVAOPTIONS],
-                    _T( "-XX:SharedArchiveFile"),
-                    FBootFields->FAppCDSCacheFileName) == true) {
-                // File names may contain the incorrect path separators.
-                // The cache file name must be corrected at this point.
-                if (FBootFields->FAppCDSCacheFileName.empty() == false) {
-                    IniFile* iniConfig = dynamic_cast<IniFile*>(Config);
-
-                    if (iniConfig != NULL) {
-                        FBootFields->FAppCDSCacheFileName =
-                                FilePath::FixPathForPlatform(
-                                FBootFields->FAppCDSCacheFileName);
-                        iniConfig->SetValue(keys[
-                                CONFIG_SECTION_APPCDSJAVAOPTIONS],
-                                _T( "-XX:SharedArchiveFile"),
-                                FBootFields->FAppCDSCacheFileName);
-                    }
-                }
-
-                Config->GetSection(keys[CONFIG_SECTION_APPCDSJAVAOPTIONS],
-                        FBootFields->FJavaOptions);
-            }
-
-            break;
-        }
-    }
-}
-
-void Package::SetCommandLineArguments(int argc, TCHAR* argv[]) {
-    if (argc > 0) {
-        std::list<TString> args;
-
-        // Prepare app arguments. Skip value at index 0 -
-        // this is path to executable.
-        FBootFields->FCommandName = argv[0];
-
-        // Path to executable is at 0 index so start at index 1.
-        for (int index = 1; index < argc; index++) {
-            TString arg = argv[index];
-
-#ifdef DEBUG
-            if (arg == _T("-debug")) {
-                FDebugging = dsNative;
-            }
-
-            if (arg == _T("-javadebug")) {
-                FDebugging = dsJava;
-            }
-#endif //DEBUG
-#ifdef MAC
-            if (arg.find(_T("-psn_"), 0) != TString::npos) {
-                Platform& platform = Platform::GetInstance();
-
-                if (platform.IsMainThread() == true) {
-#ifdef DEBUG
-                    printf("%s\n", arg.c_str());
-#endif //DEBUG
-                    continue;
-                }
-            }
-
-            if (arg == _T("-NSDocumentRevisionsDebugMode")) {
-                // Ignore -NSDocumentRevisionsDebugMode and
-                // the following YES/NO
-                index++;
-                continue;
-            }
-#endif //MAC
-
-            args.push_back(arg);
-        }
-
-        if (args.size() > 0) {
-            FBootFields->FArgs = args;
-        }
-    }
-}
-
-Package& Package::GetInstance() {
-    static Package instance;
-    // Guaranteed to be destroyed. Instantiated on first use.
-    return instance;
-}
-
-Package::~Package(void) {
-    FreeBootFields();
-}
-
-void Package::FreeBootFields() {
-    if (FBootFields != NULL) {
-        delete FBootFields;
-        FBootFields = NULL;
-    }
-}
-
-OrderedMap<TString, TString> Package::GetJavaOptions() {
-    return FBootFields->FJavaOptions;
-}
-
-std::vector<TString> GetKeysThatAreNotDuplicates(OrderedMap<TString,
-        TString> &Defaults, OrderedMap<TString, TString> &Overrides) {
-    std::vector<TString> result;
-    std::vector<TString> overrideKeys = Overrides.GetKeys();
-
-    for (size_t index = 0; index < overrideKeys.size(); index++) {
-        TString overridesKey = overrideKeys[index];
-        TString overridesValue;
-        TString defaultValue;
-
-        if ((Defaults.ContainsKey(overridesKey) == false) ||
-           (Defaults.GetValue(overridesKey, defaultValue) == true &&
-            Overrides.GetValue(overridesKey, overridesValue) == true &&
-            defaultValue != overridesValue)) {
-            result.push_back(overridesKey);
-        }
-    }
-
-    return result;
-}
-
-OrderedMap<TString, TString> CreateOrderedMapFromKeyList(OrderedMap<TString,
-        TString> &Map, std::vector<TString> &Keys) {
-    OrderedMap<TString, TString> result;
-
-    for (size_t index = 0; index < Keys.size(); index++) {
-        TString key = Keys[index];
-        TString value;
-
-        if (Map.GetValue(key, value) == true) {
-            result.Append(key, value);
-        }
-    }
-
-    return result;
-}
-
-std::vector<TString> GetKeysThatAreNotOverridesOfDefaultValues(
-        OrderedMap<TString, TString> &Defaults, OrderedMap<TString,
-        TString> &Overrides) {
-    std::vector<TString> result;
-    std::vector<TString> keys = Overrides.GetKeys();
-
-    for (unsigned int index = 0; index< keys.size(); index++) {
-        TString key = keys[index];
-
-        if (Defaults.ContainsKey(key) == true) {
-            try {
-                TString value = Overrides[key];
-                Defaults[key] = value;
-            }
-            catch (std::out_of_range &) {
-            }
-        }
-        else {
-            result.push_back(key);
-        }
-    }
-
-    return result;
-}
-
-std::list<TString> Package::GetArgs() {
-    assert(FBootFields != NULL);
-    return FBootFields->FArgs;
-}
-
-TString Package::GetPackageRootDirectory() {
-    assert(FBootFields != NULL);
-    return FBootFields->FPackageRootDirectory;
-}
-
-TString Package::GetPackageAppDirectory() {
-    assert(FBootFields != NULL);
-    return FBootFields->FPackageAppDirectory;
-}
-
-TString Package::GetPackageLauncherDirectory() {
-    assert(FBootFields != NULL);
-    return FBootFields->FPackageLauncherDirectory;
-}
-
-TString Package::GetAppDataDirectory() {
-    assert(FBootFields != NULL);
-    return FBootFields->FAppDataDirectory;
-}
-
-TString Package::GetAppCDSCacheDirectory() {
-    if (FAppCDSCacheDirectory.empty()) {
-        Platform& platform = Platform::GetInstance();
-        FAppCDSCacheDirectory = FilePath::IncludeTrailingSeparator(
-                platform.GetAppDataDirectory())
-                + FilePath::IncludeTrailingSeparator(
-                GetPackageAppDataDirectory()) + _T("cache");
-
-        Macros& macros = Macros::GetInstance();
-        FAppCDSCacheDirectory = macros.ExpandMacros(FAppCDSCacheDirectory);
-        FAppCDSCacheDirectory =
-                FilePath::FixPathForPlatform(FAppCDSCacheDirectory);
-    }
-
-    return FAppCDSCacheDirectory;
-}
-
-TString Package::GetAppCDSCacheFileName() {
-    assert(FBootFields != NULL);
-
-    if (FBootFields->FAppCDSCacheFileName.empty() == false) {
-        Macros& macros = Macros::GetInstance();
-        FBootFields->FAppCDSCacheFileName =
-                macros.ExpandMacros(FBootFields->FAppCDSCacheFileName);
-        FBootFields->FAppCDSCacheFileName =
-                FilePath::FixPathForPlatform(FBootFields->FAppCDSCacheFileName);
-    }
-
-    return FBootFields->FAppCDSCacheFileName;
-}
-
-TString Package::GetPackageAppDataDirectory() {
-    assert(FBootFields != NULL);
-    return FBootFields->FPackageAppDataDirectory;
-}
-
-TString Package::GetClassPath() {
-    assert(FBootFields != NULL);
-    return FBootFields->FClassPath;
-}
-
-TString Package::GetModulePath() {
-    assert(FBootFields != NULL);
-    return FBootFields->FModulePath;
-}
-
-TString Package::GetMainJar() {
-    assert(FBootFields != NULL);
-    return FBootFields->FMainJar;
-}
-
-TString Package::GetMainModule() {
-    assert(FBootFields != NULL);
-    return FBootFields->FMainModule;
-}
-
-TString Package::GetMainClassName() {
-    assert(FBootFields != NULL);
-    return FBootFields->FMainClassName;
-}
-
-TString Package::GetJavaLibraryFileName() {
-    assert(FBootFields != NULL);
-
-    if (FBootFields->FJavaLibraryFileName.empty() == true) {
-        Platform& platform = Platform::GetInstance();
-        Macros& macros = Macros::GetInstance();
-        TString jvmRuntimePath = macros.ExpandMacros(GetJavaRuntimeDirectory());
-        FBootFields->FJavaLibraryFileName =
-                platform.GetBundledJavaLibraryFileName(jvmRuntimePath);
-    }
-
-    return FBootFields->FJavaLibraryFileName;
-}
-
-TString Package::GetJavaRuntimeDirectory() {
-    assert(FBootFields != NULL);
-    return FBootFields->FJavaRuntimeDirectory;
-}
-
-TString Package::GetSplashScreenFileName() {
-    assert(FBootFields != NULL);
-    return FBootFields->FSplashScreenFileName;
-}
-
-bool Package::HasSplashScreen() {
-    assert(FBootFields != NULL);
-    return FilePath::FileExists(FBootFields->FSplashScreenFileName);
-}
-
-TString Package::GetCommandName() {
-    assert(FBootFields != NULL);
-    return FBootFields->FCommandName;
-}
-
-TPlatformNumber Package::GetMemorySize() {
-    assert(FBootFields != NULL);
-    return FBootFields->FMemorySize;
-}
-
-PackageBootFields::MemoryState Package::GetMemoryState() {
-    assert(FBootFields != NULL);
-    return FBootFields->FMemoryState;
-}
-
-DebugState Package::Debugging() {
-    return FDebugging;
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/Package.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef PACKAGE_H
-#define PACKAGE_H
-
-
-#include "Platform.h"
-#include "PlatformString.h"
-#include "FilePath.h"
-#include "PropertyFile.h"
-
-#include <map>
-#include <list>
-
-class PackageBootFields {
-public:
-    enum MemoryState {msManual, msAuto};
-
-public:
-    OrderedMap<TString, TString> FJavaOptions;
-    std::list<TString> FArgs;
-
-    TString FPackageRootDirectory;
-    TString FPackageAppDirectory;
-    TString FPackageLauncherDirectory;
-    TString FAppDataDirectory;
-    TString FPackageAppDataDirectory;
-    TString FClassPath;
-    TString FModulePath;
-    TString FMainJar;
-    TString FMainModule;
-    TString FMainClassName;
-    TString FJavaRuntimeDirectory;
-    TString FJavaLibraryFileName;
-    TString FSplashScreenFileName;
-    bool FUseJavaPreferences;
-    TString FCommandName;
-
-    TString FAppCDSCacheFileName;
-
-    TPlatformNumber FMemorySize;
-    MemoryState FMemoryState;
-};
-
-
-class Package {
-private:
-    Package(Package const&); // Don't Implement.
-    void operator=(Package const&); // Don't implement
-
-private:
-    bool FInitialized;
-    PackageBootFields* FBootFields;
-    TString FAppCDSCacheDirectory;
-
-    DebugState FDebugging;
-
-    Package(void);
-
-    TString GetMainJar();
-    void ReadJavaOptions(ISectionalPropertyContainer* Config);
-    void PromoteAppCDSState(ISectionalPropertyContainer* Config);
-
-public:
-    static Package& GetInstance();
-    ~Package(void);
-
-    void Initialize();
-    void Clear();
-    void FreeBootFields();
-
-    void SetCommandLineArguments(int argc, TCHAR* argv[]);
-
-    OrderedMap<TString, TString> GetJavaOptions();
-    TString GetMainModule();
-
-    std::list<TString> GetArgs();
-
-    TString GetPackageRootDirectory();
-    TString GetPackageAppDirectory();
-    TString GetPackageLauncherDirectory();
-    TString GetAppDataDirectory();
-
-    TString GetAppCDSCacheDirectory();
-    TString GetAppCDSCacheFileName();
-
-    TString GetPackageAppDataDirectory();
-    TString GetClassPath();
-    TString GetModulePath();
-    TString GetMainClassName();
-    TString GetJavaLibraryFileName();
-    TString GetJavaRuntimeDirectory();
-    TString GetSplashScreenFileName();
-    bool HasSplashScreen();
-    TString GetCommandName();
-
-    TPlatformNumber GetMemorySize();
-    PackageBootFields::MemoryState GetMemoryState();
-
-    DebugState Debugging();
-};
-
-#endif // PACKAGE_H
--- a/src/jdk.jpackage/share/native/libapplauncher/Platform.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "Platform.h"
-#include "Messages.h"
-#include "PlatformString.h"
-#include "FilePath.h"
-
-#include <fstream>
-#include <locale>
-
-#ifdef WINDOWS
-#include "WindowsPlatform.h"
-#endif // WINDOWS
-#ifdef LINUX
-#include "LinuxPlatform.h"
-#endif // LINUX
-#ifdef MAC
-#include "MacPlatform.h"
-#endif // MAC
-
-Platform& Platform::GetInstance() {
-#ifdef WINDOWS
-    static WindowsPlatform instance;
-#endif // WINDOWS
-
-#ifdef LINUX
-    static LinuxPlatform instance;
-#endif // LINUX
-
-#ifdef MAC
-    static MacPlatform instance;
-#endif // MAC
-
-    return instance;
-}
-
-TString Platform::GetConfigFileName() {
-    TString result;
-    TString basedir = GetPackageAppDirectory();
-
-    if (basedir.empty() == false) {
-        basedir = FilePath::IncludeTrailingSeparator(basedir);
-        TString appConfig = basedir + GetAppName() + _T(".cfg");
-
-        if (FilePath::FileExists(appConfig) == true) {
-            result = appConfig;
-        }
-        else {
-            result = basedir + _T("package.cfg");
-
-            if (FilePath::FileExists(result) == false) {
-                result = _T("");
-            }
-        }
-    }
-
-    return result;
-}
-
-std::list<TString> Platform::LoadFromFile(TString FileName) {
-    std::list<TString> result;
-
-    if (FilePath::FileExists(FileName) == true) {
-        std::wifstream stream(FileName.data());
-        InitStreamLocale(&stream);
-
-        if (stream.is_open() == true) {
-            while (stream.eof() == false) {
-                std::wstring line;
-                std::getline(stream, line);
-
-                // # at the first character will comment out the line.
-                if (line.empty() == false && line[0] != '#') {
-                    result.push_back(PlatformString(line).toString());
-                }
-            }
-        }
-    }
-
-    return result;
-}
-
-void Platform::SaveToFile(TString FileName, std::list<TString> Contents, bool ownerOnly) {
-    TString path = FilePath::ExtractFilePath(FileName);
-
-    if (FilePath::DirectoryExists(path) == false) {
-        FilePath::CreateDirectory(path, ownerOnly);
-    }
-
-    std::wofstream stream(FileName.data());
-    InitStreamLocale(&stream);
-
-    FilePath::ChangePermissions(FileName.data(), ownerOnly);
-
-    if (stream.is_open() == true) {
-        for (std::list<TString>::const_iterator iterator =
-                Contents.begin(); iterator != Contents.end(); iterator++) {
-            TString line = *iterator;
-            stream << PlatformString(line).toUnicodeString() << std::endl;
-        }
-    }
-}
-
-std::map<TString, TString> Platform::GetKeys() {
-    std::map<TString, TString> keys;
-    keys.insert(std::map<TString, TString>::value_type(CONFIG_VERSION,
-            _T("app.version")));
-    keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINJAR_KEY,
-            _T("app.mainjar")));
-    keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINMODULE_KEY,
-            _T("app.mainmodule")));
-    keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINCLASSNAME_KEY,
-            _T("app.mainclass")));
-    keys.insert(std::map<TString, TString>::value_type(CONFIG_CLASSPATH_KEY,
-            _T("app.classpath")));
-    keys.insert(std::map<TString, TString>::value_type(CONFIG_MODULEPATH_KEY,
-            _T("app.modulepath")));
-    keys.insert(std::map<TString, TString>::value_type(APP_NAME_KEY,
-            _T("app.name")));
-    keys.insert(std::map<TString, TString>::value_type(JAVA_RUNTIME_KEY,
-            _T("app.runtime")));
-    keys.insert(std::map<TString, TString>::value_type(JPACKAGE_APP_DATA_DIR,
-            _T("app.identifier")));
-    keys.insert(std::map<TString, TString>::value_type(CONFIG_SPLASH_KEY,
-            _T("app.splash")));
-    keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_MEMORY,
-            _T("app.memory")));
-    keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_DEBUG,
-            _T("app.debug")));
-    keys.insert(std::map<TString,
-            TString>::value_type(CONFIG_APPLICATION_INSTANCE,
-            _T("app.application.instance")));
-    keys.insert(std::map<TString,
-            TString>::value_type(CONFIG_SECTION_APPLICATION,
-            _T("Application")));
-    keys.insert(std::map<TString,
-            TString>::value_type(CONFIG_SECTION_JAVAOPTIONS,
-            _T("JavaOptions")));
-    keys.insert(std::map<TString,
-            TString>::value_type(CONFIG_SECTION_APPCDSJAVAOPTIONS,
-            _T("AppCDSJavaOptions")));
-    keys.insert(std::map<TString,
-            TString>::value_type(CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS,
-            _T("AppCDSGenerateCacheJavaOptions")));
-    keys.insert(std::map<TString,
-            TString>::value_type(CONFIG_SECTION_ARGOPTIONS,
-            _T("ArgOptions")));
-
-    return keys;
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/Platform.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,264 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef PLATFORM_H
-#define PLATFORM_H
-
-#include "PlatformDefs.h"
-#include "Properties.h"
-#include "OrderedMap.h"
-#include "Library.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <string>
-#include <map>
-#include <list>
-#include <vector>
-#include <fstream>
-
-using namespace std;
-
-// Config file sections
-#define CONFIG_SECTION_APPLICATION        _T("CONFIG_SECTION_APPLICATION")
-#define CONFIG_SECTION_JAVAOPTIONS        _T("CONFIG_SECTION_JAVAOPTIONS")
-#define CONFIG_SECTION_APPCDSJAVAOPTIONS  _T("CONFIG_SECTION_APPCDSJAVAOPTIONS")
-#define CONFIG_SECTION_ARGOPTIONS         _T("CONFIG_SECTION_ARGOPTIONS")
-#define CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS \
-        _T("CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS")
-
-// Config file keys.
-#define CONFIG_VERSION            _T("CONFIG_VERSION")
-#define CONFIG_MAINJAR_KEY        _T("CONFIG_MAINJAR_KEY")
-#define CONFIG_MAINMODULE_KEY     _T("CONFIG_MAINMODULE_KEY")
-#define CONFIG_MAINCLASSNAME_KEY  _T("CONFIG_MAINCLASSNAME_KEY")
-#define CONFIG_CLASSPATH_KEY      _T("CONFIG_CLASSPATH_KEY")
-#define CONFIG_MODULEPATH_KEY     _T("CONFIG_MODULEPATH_KEY")
-#define APP_NAME_KEY              _T("APP_NAME_KEY")
-#define CONFIG_SPLASH_KEY         _T("CONFIG_SPLASH_KEY")
-#define CONFIG_APP_MEMORY         _T("CONFIG_APP_MEMORY")
-#define CONFIG_APP_DEBUG          _T("CONFIG_APP_DEBUG")
-#define CONFIG_APPLICATION_INSTANCE _T("CONFIG_APPLICATION_INSTANCE")
-
-#define JAVA_RUNTIME_KEY           _T("JAVA_RUNTIME_KEY")
-#define JPACKAGE_APP_DATA_DIR     _T("CONFIG_APP_IDENTIFIER")
-
-struct WideString {
-    size_t length;
-    wchar_t* data;
-
-    WideString() { length = 0; data = NULL; }
-};
-
-struct MultibyteString {
-    size_t length;
-    char* data;
-
-    MultibyteString() { length = 0; data = NULL; }
-};
-
-class Process {
-protected:
-    std::list<TString> FOutput;
-
-public:
-    Process() {
-        Output.SetInstance(this);
-        Input.SetInstance(this);
-    }
-
-    virtual ~Process() {}
-
-    virtual bool IsRunning() = 0;
-    virtual bool Terminate() = 0;
-    virtual bool Execute(const TString Application,
-        const std::vector<TString> Arguments, bool AWait = false) = 0;
-    virtual bool Wait() = 0;
-    virtual TProcessID GetProcessID() = 0;
-
-    virtual std::list<TString> GetOutput() { return FOutput; }
-    virtual void SetInput(TString Value) = 0;
-
-    ReadProperty<Process, std::list<TString>, &Process::GetOutput> Output;
-    WriteProperty<Process, TString, &Process::SetInput> Input;
-};
-
-
-template <typename T>
-class AutoFreePtr {
-private:
-    T* FObject;
-
-public:
-    AutoFreePtr() {
-        FObject = NULL;
-    }
-
-    AutoFreePtr(T* Value) {
-        FObject = Value;
-    }
-
-    ~AutoFreePtr() {
-        if (FObject != NULL) {
-            delete FObject;
-        }
-    }
-
-    operator T* () const {
-        return FObject;
-    }
-
-    T& operator* () const {
-        return *FObject;
-    }
-
-    T* operator->() const {
-        return FObject;
-    }
-
-    T** operator&() {
-        return &FObject;
-    }
-
-    T* operator=(const T * rhs) {
-        FObject = rhs;
-        return FObject;
-    }
-};
-
-enum DebugState {dsNone, dsNative, dsJava};
-enum MessageResponse {mrOK, mrCancel};
-enum AppCDSState {cdsUninitialized, cdsDisabled,
-        cdsEnabled, cdsAuto, cdsGenCache};
-
-class Platform {
-private:
-    AppCDSState FAppCDSState;
-
-protected:
-    Platform(void): FAppCDSState(cdsUninitialized) {
-    }
-
-public:
-    AppCDSState GetAppCDSState() { return FAppCDSState; }
-    void SetAppCDSState(AppCDSState Value) { FAppCDSState = Value; }
-
-    static Platform& GetInstance();
-
-    virtual ~Platform(void) {}
-
-public:
-    virtual void ShowMessage(TString title, TString description) = 0;
-    virtual void ShowMessage(TString description) = 0;
-    virtual MessageResponse ShowResponseMessage(TString title,
-           TString description) = 0;
-
-    // Caller must free result using delete[].
-    virtual TCHAR* ConvertStringToFileSystemString(TCHAR* Source,
-            bool &release) = 0;
-
-    // Caller must free result using delete[].
-    virtual TCHAR* ConvertFileSystemStringToString(TCHAR* Source,
-            bool &release) = 0;
-
-    // Returns:
-    // Windows=C:\Users\<username>\AppData\Local
-    // Linux=~/.local
-    // Mac=~/Library/Application Support
-    virtual TString GetAppDataDirectory() = 0;
-
-    virtual TString GetPackageAppDirectory() = 0;
-    virtual TString GetPackageLauncherDirectory() = 0;
-    virtual TString GetPackageRuntimeBinDirectory() = 0;
-    virtual TString GetAppName() = 0;
-
-    virtual TString GetConfigFileName();
-
-    virtual TString GetBundledJavaLibraryFileName(TString RuntimePath) = 0;
-
-    // Caller must free result.
-    virtual ISectionalPropertyContainer* GetConfigFile(TString FileName) = 0;
-
-    virtual TString GetModuleFileName() = 0;
-    virtual TString GetPackageRootDirectory() = 0;
-
-    virtual Module LoadLibrary(TString FileName) = 0;
-    virtual void FreeLibrary(Module Module) = 0;
-    virtual Procedure GetProcAddress(Module Module, std::string MethodName) = 0;
-
-    // Caller must free result.
-    virtual Process* CreateProcess() = 0;
-
-    virtual bool IsMainThread() = 0;
-
-    // Returns megabytes.
-    virtual TPlatformNumber GetMemorySize() = 0;
-
-    virtual std::map<TString, TString> GetKeys();
-
-    virtual void InitStreamLocale(wios *stream) = 0;
-    virtual std::list<TString> LoadFromFile(TString FileName);
-    virtual void SaveToFile(TString FileName,
-             std::list<TString> Contents, bool ownerOnly);
-
-    virtual TString GetTempDirectory() = 0;
-
-    virtual void addPlatformDependencies(JavaLibrary *pJavaLibrary) = 0;
-
-public:
-    // String helpers
-    // Caller must free result using delete[].
-    static void CopyString(char *Destination,
-            size_t NumberOfElements, const char *Source);
-
-    // Caller must free result using delete[].
-    static void CopyString(wchar_t *Destination,
-            size_t NumberOfElements, const wchar_t *Source);
-
-    static WideString MultibyteStringToWideString(const char* value);
-    static MultibyteString WideStringToMultibyteString(const wchar_t* value);
-};
-
-class Exception: public std::exception {
-private:
-    TString FMessage;
-
-protected:
-    void SetMessage(const TString Message) {
-        FMessage = Message;
-    }
-
-public:
-    explicit Exception() : exception() {}
-    explicit Exception(const TString Message) : exception() {
-        SetMessage(Message);
-    }
-    virtual ~Exception() throw() {}
-
-    TString GetMessage() { return FMessage; }
-};
-
-#endif // PLATFORM_H
--- a/src/jdk.jpackage/share/native/libapplauncher/PlatformString.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "PlatformString.h"
-
-#include "Helpers.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <sstream>
-#include <string.h>
-
-#include "jni.h"
-
-void PlatformString::initialize() {
-    FWideTStringToFree = NULL;
-    FLength = 0;
-    FData = NULL;
-}
-
-PlatformString::PlatformString(void) {
-    initialize();
-}
-
-PlatformString::~PlatformString(void) {
-    if (FData != NULL) {
-        delete[] FData;
-    }
-
-    if (FWideTStringToFree != NULL) {
-        delete[] FWideTStringToFree;
-    }
-}
-
-PlatformString::PlatformString(const PlatformString &value) {
-    initialize();
-    FLength = value.FLength;
-    FData = new char[FLength + 1];
-    Platform::CopyString(FData, FLength + 1, value.FData);
-}
-
-PlatformString::PlatformString(const char* value) {
-    initialize();
-    FLength = strlen(value);
-    FData = new char[FLength + 1];
-    Platform::CopyString(FData, FLength + 1, value);
-}
-
-PlatformString::PlatformString(size_t Value) {
-    initialize();
-
-    std::stringstream ss;
-    std::string s;
-    ss << Value;
-    s = ss.str();
-
-    FLength = strlen(s.c_str());
-    FData = new char[FLength + 1];
-    Platform::CopyString(FData, FLength + 1, s.c_str());
-}
-
-PlatformString::PlatformString(const wchar_t* value) {
-    initialize();
-    MultibyteString temp = Platform::WideStringToMultibyteString(value);
-    FLength = temp.length;
-    FData = temp.data;
-}
-
-PlatformString::PlatformString(const std::string &value) {
-    initialize();
-    const char* lvalue = value.data();
-    FLength = value.size();
-    FData = new char[FLength + 1];
-    Platform::CopyString(FData, FLength + 1, lvalue);
-}
-
-PlatformString::PlatformString(const std::wstring &value) {
-    initialize();
-    const wchar_t* lvalue = value.data();
-    MultibyteString temp = Platform::WideStringToMultibyteString(lvalue);
-    FLength = temp.length;
-    FData = temp.data;
-}
-
-TString PlatformString::Format(const TString value, ...) {
-    TString result = value;
-
-    va_list arglist;
-    va_start(arglist, value);
-
-    while (1) {
-        size_t pos = result.find(_T("%s"), 0);
-
-        if (pos == TString::npos) {
-            break;
-        }
-        else {
-            TCHAR* arg = va_arg(arglist, TCHAR*);
-
-            if (arg == NULL) {
-                break;
-            }
-            else {
-                result.replace(pos, StringLength(_T("%s")), arg);
-            }
-        }
-    }
-
-    va_end(arglist);
-
-    return result;
-}
-
-size_t PlatformString::length() {
-    return FLength;
-}
-
-char* PlatformString::c_str() {
-    return FData;
-}
-
-char* PlatformString::toMultibyte() {
-    return FData;
-}
-
-wchar_t* PlatformString::toWideString() {
-    WideString result = Platform::MultibyteStringToWideString(FData);
-
-    if (result.data != NULL) {
-        if (FWideTStringToFree != NULL) {
-            delete [] FWideTStringToFree;
-        }
-
-        FWideTStringToFree = result.data;
-    }
-
-    return result.data;
-}
-
-std::wstring PlatformString::toUnicodeString() {
-    std::wstring result;
-    wchar_t* data = toWideString();
-
-    if (FLength != 0 && data != NULL) {
-        // NOTE: Cleanup of result is handled by PlatformString destructor.
-        result = data;
-    }
-
-    return result;
-}
-
-std::string PlatformString::toStdString() {
-    std::string result;
-    char* data = toMultibyte();
-
-    if (FLength > 0 && data != NULL) {
-        result = data;
-    }
-
-    return result;
-}
-
-TCHAR* PlatformString::toPlatformString() {
-#ifdef _UNICODE
-    return toWideString();
-#else
-    return c_str();
-#endif //_UNICODE
-}
-
-TString PlatformString::toString() {
-#ifdef _UNICODE
-    return toUnicodeString();
-#else
-    return toStdString();
-#endif //_UNICODE
-}
-
-PlatformString::operator char* () {
-    return c_str();
-}
-
-PlatformString::operator wchar_t* () {
-    return toWideString();
-}
-
-PlatformString::operator std::wstring () {
-    return toUnicodeString();
-}
-
-char* PlatformString::duplicate(const char* Value) {
-    size_t length = strlen(Value);
-    char* result = new char[length + 1];
-    Platform::CopyString(result, length + 1, Value);
-    return result;
-}
-
-wchar_t* PlatformString::duplicate(const wchar_t* Value) {
-    size_t length = wcslen(Value);
-    wchar_t* result = new wchar_t[length + 1];
-    Platform::CopyString(result, length + 1, Value);
-    return result;
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/PlatformString.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef PLATFORMSTRING_H
-#define PLATFORMSTRING_H
-
-
-#include <string>
-#include <list>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "jni.h"
-#include "Platform.h"
-
-
-template <typename T>
-class DynamicBuffer {
-private:
-    T* FData;
-    size_t FSize;
-
-public:
-    DynamicBuffer(size_t Size) {
-        FSize = 0;
-        FData = NULL;
-        Resize(Size);
-    }
-
-    ~DynamicBuffer() {
-        delete[] FData;
-    }
-
-    T* GetData() { return FData; }
-    size_t GetSize() { return FSize; }
-
-    bool Resize(size_t Size) {
-        FSize = Size;
-
-        if (FData != NULL) {
-            delete[] FData;
-            FData = NULL;
-        }
-
-        if (FSize != 0) {
-            FData = new T[FSize];
-            if (FData != NULL) {
-                Zero();
-            } else {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    void Zero() {
-        memset(FData, 0, FSize * sizeof(T));
-    }
-
-    T& operator[](size_t index) {
-        return FData[index];
-    }
-};
-
-class PlatformString {
-private:
-    char* FData; // Stored as UTF-8
-    size_t FLength;
-    wchar_t* FWideTStringToFree;
-
-    void initialize();
-
-// Prohibit Heap-Based PlatformStrings
-private:
-    static void *operator new(size_t size);
-    static void operator delete(void *ptr);
-
-public:
-    PlatformString(void);
-    PlatformString(const PlatformString &value);
-    PlatformString(const char* value);
-    PlatformString(const wchar_t* value);
-    PlatformString(const std::string &value);
-    PlatformString(const std::wstring &value);
-    PlatformString(size_t Value);
-
-    static TString Format(const TString value, ...);
-
-    ~PlatformString(void);
-
-    size_t length();
-
-    char* c_str();
-    char* toMultibyte();
-    wchar_t* toWideString();
-    std::wstring toUnicodeString();
-    std::string toStdString();
-    TCHAR* toPlatformString();
-    TString toString();
-
-    operator char* ();
-    operator wchar_t* ();
-    operator std::wstring ();
-
-    // Caller must free result using delete[].
-    static char* duplicate(const char* Value);
-
-    // Caller must free result using delete[].
-    static wchar_t* duplicate(const wchar_t* Value);
-};
-
-
-#endif // PLATFORMSTRING_H
--- a/src/jdk.jpackage/share/native/libapplauncher/Properties.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef PROPERTIES_H
-#define PROPERTIES_H
-
-#include "PlatformDefs.h"
-#include "OrderedMap.h"
-
-//#include <stdio.h>
-//#include <stdlib.h>
-//#include <memory.h>
-//#include <string>
-//#include <map>
-//#include <list>
-//#include <vector>
-//#include <fstream>
-
-//using namespace std;
-
-template <typename ObjectType, typename ValueType,
-        ValueType (ObjectType::*getter)(void),
-        void (ObjectType::*setter)(ValueType)>
-class Property {
-private:
-    ObjectType* FObject;
-
-public:
-    Property() {
-        FObject = NULL;
-    }
-
-    void SetInstance(ObjectType* Value) {
-        FObject = Value;
-    }
-
-    // To set the value using the set method.
-    ValueType operator =(const ValueType& Value) {
-        assert(FObject != NULL);
-        (FObject->*setter)(Value);
-        return Value;
-    }
-
-    // The Property class is treated as the internal type.
-    operator ValueType() {
-        assert(FObject != NULL);
-        return (FObject->*getter)();
-    }
-};
-
-template <typename ObjectType, typename ValueType,
-        ValueType (ObjectType::*getter)(void)>
-class ReadProperty {
-private:
-    ObjectType* FObject;
-
-public:
-    ReadProperty() {
-        FObject = NULL;
-    }
-
-    void SetInstance(ObjectType* Value) {
-        FObject = Value;
-    }
-
-    // The Property class is treated as the internal type.
-    operator ValueType() {
-        assert(FObject != NULL);
-        return (FObject->*getter)();
-    }
-};
-
-template <typename ObjectType, typename ValueType,
-        void (ObjectType::*setter)(ValueType)>
-class WriteProperty {
-private:
-    ObjectType* FObject;
-
-public:
-    WriteProperty() {
-        FObject = NULL;
-    }
-
-    void SetInstance(ObjectType* Value) {
-        FObject = Value;
-    }
-
-    // To set the value using the set method.
-    ValueType operator =(const ValueType& Value) {
-        assert(FObject != NULL);
-        (FObject->*setter)(Value);
-        return Value;
-    }
-};
-
-template <typename ValueType,
-        ValueType (*getter)(void), void (*setter)(ValueType)>
-class StaticProperty {
-public:
-    StaticProperty() {
-    }
-
-    // To set the value using the set method.
-    ValueType operator =(const ValueType& Value) {
-        (*getter)(Value);
-        return Value;
-    }
-
-    // The Property class is treated as the internal type which is the getter.
-    operator ValueType() {
-        return (*setter)();
-    }
-};
-
-template <typename ValueType, ValueType (*getter)(void)>
-class StaticReadProperty {
-public:
-    StaticReadProperty() {
-    }
-
-    // The Property class is treated as the internal type which is the getter.
-    operator ValueType() {
-        return (*getter)();
-    }
-};
-
-template <typename ValueType, void (*setter)(ValueType)>
-class StaticWriteProperty {
-public:
-    StaticWriteProperty() {
-    }
-
-    // To set the value using the set method.
-    ValueType operator =(const ValueType& Value) {
-        (*setter)(Value);
-        return Value;
-    }
-};
-
-class IPropertyContainer {
-public:
-    IPropertyContainer(void) {}
-    virtual ~IPropertyContainer(void) {}
-
-    virtual bool GetValue(const TString Key, TString& Value) = 0;
-    virtual size_t GetCount() = 0;
-};
-
-class ISectionalPropertyContainer {
-public:
-    ISectionalPropertyContainer(void) {}
-    virtual ~ISectionalPropertyContainer(void) {}
-
-    virtual bool GetValue(const TString SectionName,
-            const TString Key, TString& Value) = 0;
-    virtual bool ContainsSection(const TString SectionName) = 0;
-    virtual bool GetSection(const TString SectionName,
-            OrderedMap<TString, TString> &Data) = 0;
-};
-
-#endif // PROPERTIES_H
-
--- a/src/jdk.jpackage/share/native/libapplauncher/PropertyFile.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "PropertyFile.h"
-
-#include "Helpers.h"
-#include "FilePath.h"
-
-#include <string>
-
-
-PropertyFile::PropertyFile(void) : IPropertyContainer() {
-    FReadOnly = false;
-    FModified = false;
-}
-
-PropertyFile::PropertyFile(const TString FileName) : IPropertyContainer() {
-    FReadOnly = true;
-    FModified = false;
-    LoadFromFile(FileName);
-}
-
-PropertyFile::PropertyFile(OrderedMap<TString, TString> Value) {
-    FData.Append(Value);
-}
-
-PropertyFile::PropertyFile(PropertyFile &Value) {
-    FData = Value.FData;
-    FReadOnly = Value.FReadOnly;
-    FModified = Value.FModified;
-}
-
-PropertyFile::~PropertyFile(void) {
-    FData.Clear();
-}
-
-void PropertyFile::SetModified(bool Value) {
-    FModified = Value;
-}
-
-bool PropertyFile::IsModified() {
-    return FModified;
-}
-
-bool PropertyFile::GetReadOnly() {
-    return FReadOnly;
-}
-
-void PropertyFile::SetReadOnly(bool Value) {
-    FReadOnly = Value;
-}
-
-bool PropertyFile::LoadFromFile(const TString FileName) {
-    bool result = false;
-    Platform& platform = Platform::GetInstance();
-
-    std::list<TString> contents = platform.LoadFromFile(FileName);
-
-    if (contents.empty() == false) {
-        for (std::list<TString>::const_iterator iterator = contents.begin();
-                iterator != contents.end(); iterator++) {
-            TString line = *iterator;
-            TString name;
-            TString value;
-
-            if (Helpers::SplitOptionIntoNameValue(line, name, value) == true) {
-                FData.Append(name, value);
-            }
-        }
-
-        SetModified(false);
-        result = true;
-    }
-
-    return result;
-}
-
-bool PropertyFile::SaveToFile(const TString FileName, bool ownerOnly) {
-    bool result = false;
-
-    if (GetReadOnly() == false && IsModified()) {
-        std::list<TString> contents;
-        std::vector<TString> keys = FData.GetKeys();
-
-        for (size_t index = 0; index < keys.size(); index++) {
-            TString name = keys[index];
-
-            try {
-                TString value;// = FData[index];
-
-                if (FData.GetValue(name, value) == true) {
-                    TString line = name + _T('=') + value;
-                    contents.push_back(line);
-                }
-            }
-            catch (std::out_of_range &) {
-            }
-        }
-
-        Platform& platform = Platform::GetInstance();
-        platform.SaveToFile(FileName, contents, ownerOnly);
-
-        SetModified(false);
-        result = true;
-    }
-
-    return result;
-}
-
-bool PropertyFile::GetValue(const TString Key, TString& Value) {
-    return FData.GetValue(Key, Value);
-}
-
-bool PropertyFile::SetValue(const TString Key, TString Value) {
-    bool result = false;
-
-    if (GetReadOnly() == false) {
-        FData.SetValue(Key, Value);
-        SetModified(true);
-        result = true;
-    }
-
-    return result;
-}
-
-bool PropertyFile::RemoveKey(const TString Key) {
-    bool result = false;
-
-    if (GetReadOnly() == false) {
-        result = FData.RemoveByKey(Key);
-
-        if (result == true) {
-            SetModified(true);
-        }
-    }
-
-    return result;
-}
-
-size_t PropertyFile::GetCount() {
-    return FData.Count();
-}
-
-OrderedMap<TString, TString> PropertyFile::GetData() {
-    return FData;
-}
--- a/src/jdk.jpackage/share/native/libapplauncher/PropertyFile.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef PROPERTYFILE_H
-#define PROPERTYFILE_H
-
-#include "Platform.h"
-#include "Helpers.h"
-
-
-class PropertyFile : public IPropertyContainer {
-private:
-    bool FReadOnly;
-    bool FModified;
-    OrderedMap<TString, TString> FData;
-
-    void SetModified(bool Value);
-
-public:
-    PropertyFile(void);
-    PropertyFile(const TString FileName);
-    PropertyFile(OrderedMap<TString, TString> Value);
-    PropertyFile(PropertyFile &Value);
-    virtual ~PropertyFile(void);
-
-    bool IsModified();
-    bool GetReadOnly();
-    void SetReadOnly(bool Value);
-
-    bool LoadFromFile(const TString FileName);
-    bool SaveToFile(const TString FileName, bool ownerOnly = true);
-
-    bool SetValue(const TString Key, TString Value);
-    bool RemoveKey(const TString Key);
-
-    OrderedMap<TString, TString> GetData();
-
-    // IPropertyContainer
-    virtual bool GetValue(const TString Key, TString& Value);
-    virtual size_t GetCount();
-};
-
-#endif // PROPERTYFILE_H
--- a/src/jdk.jpackage/share/native/libapplauncher/main.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "Platform.h"
-#include "PlatformString.h"
-#include "FilePath.h"
-#include "PropertyFile.h"
-#include "JavaVirtualMachine.h"
-#include "Package.h"
-#include "Macros.h"
-#include "Messages.h"
-
-#include <stdio.h>
-#include <signal.h>
-#include <stdlib.h>
-
-/*
-This is the app launcher program for application packaging on Windows, Mac,
-    and Linux.
-
-Basic approach:
-  - Launcher (jpackageapplauncher) is executable that loads
-    applauncher.dll/libapplauncher.dylib/libapplauncher.so
-    and calls start_launcher below.
-  - Reads app/package.cfg or Info.plist or app/<appname>.cfg for application
-    launch configuration (package.cfg is property file).
-  - Load Java with requested Java settings (bundled client Java if availble,
-    server or installed Java otherwise).
-  - Wait for Java to exit and then exit from Main
-  - To debug application by passing command line argument.
-  - Application folder is added to the library path (so LoadLibrary()) works.
-
-Limitations and future work:
-  - Running Java code in primordial thread may cause problems
-    (example: can not use custom stack size).
-    Solution used by java launcher is to create a new thread to invoke Java.
-    See CR 6316197 for more information.
-*/
-
-extern "C" {
-
-    JNIEXPORT bool start_launcher(int argc, TCHAR* argv[]) {
-        bool result = false;
-        bool parentProcess = true;
-
-        // Platform must be initialize first.
-        Platform& platform = Platform::GetInstance();
-
-        try {
-            for (int index = 0; index < argc; index++) {
-                TString argument = argv[index];
-
-                if (argument == _T("-Xappcds:generatecache")) {
-                    platform.SetAppCDSState(cdsGenCache);
-                }
-                else if (argument == _T("-Xappcds:off")) {
-                    platform.SetAppCDSState(cdsDisabled);
-                }
-                else if (argument == _T("-Xapp:child")) {
-                    parentProcess = false;
-                }
-            }
-
-            // Package must be initialized after Platform is fully initialized.
-            Package& package = Package::GetInstance();
-            Macros::Initialize();
-            package.SetCommandLineArguments(argc, argv);
-
-            switch (platform.GetAppCDSState()) {
-                case cdsDisabled:
-                case cdsUninitialized:
-                case cdsEnabled: {
-                    break;
-                }
-
-                case cdsGenCache: {
-                    TString cacheDirectory = package.GetAppCDSCacheDirectory();
-
-                    if (FilePath::DirectoryExists(cacheDirectory) == false) {
-                        FilePath::CreateDirectory(cacheDirectory, true);
-                    } else {
-                        TString cacheFileName =
-                                package.GetAppCDSCacheFileName();
-                        if (FilePath::FileExists(cacheFileName) == true) {
-                            FilePath::DeleteFile(cacheFileName);
-                        }
-                    }
-
-                    break;
-                }
-
-                case cdsAuto: {
-                    TString cacheFileName = package.GetAppCDSCacheFileName();
-
-                    if (parentProcess == true &&
-                            FilePath::FileExists(cacheFileName) == false) {
-                        AutoFreePtr<Process> process = platform.CreateProcess();
-                        std::vector<TString> args;
-                        args.push_back(_T("-Xappcds:generatecache"));
-                        args.push_back(_T("-Xapp:child"));
-                        process->Execute(
-                                platform.GetModuleFileName(), args, true);
-
-                        if (FilePath::FileExists(cacheFileName) == false) {
-                            // Cache does not exist after trying to generate it,
-                            // so run without cache.
-                            platform.SetAppCDSState(cdsDisabled);
-                            package.Clear();
-                            package.Initialize();
-                        }
-                    }
-
-                    break;
-                }
-            }
-
-            // Validation
-            switch (platform.GetAppCDSState()) {
-                case cdsDisabled:
-                case cdsGenCache: {
-                    // Do nothing.
-                    break;
-                }
-
-                case cdsEnabled:
-                case cdsAuto: {
-                    TString cacheFileName =
-                            package.GetAppCDSCacheFileName();
-
-                    if (FilePath::FileExists(cacheFileName) == false) {
-                        Messages& messages = Messages::GetInstance();
-                        TString message = PlatformString::Format(
-                                messages.GetMessage(
-                                APPCDS_CACHE_FILE_NOT_FOUND),
-                                cacheFileName.data());
-                        throw Exception(message);
-                    }
-                    break;
-                }
-
-                case cdsUninitialized: {
-                    platform.ShowMessage(_T("Internal Error"));
-                    break;
-                }
-            }
-
-            // Run App
-            result = RunVM();
-        } catch (Exception &e) {
-            platform.ShowMessage(e.GetMessage());
-        }
-
-        return result;
-    }
-
-    JNIEXPORT void stop_launcher() {
-    }
-}
--- a/src/jdk.jpackage/unix/native/libapplauncher/FileAttribute.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef FILEATTRIBUTE_H
-#define FILEATTRIBUTE_H
-
-enum FileAttribute {
-    faBlockSpecial,
-    faCharacterSpecial,
-    faFIFOSpecial,
-    faNormal,
-    faDirectory,
-    faSymbolicLink,
-    faSocket,
-
-    // Owner
-    faReadOnly,
-    faWriteOnly,
-    faReadWrite,
-    faExecute,
-
-    // Group
-    faGroupReadOnly,
-    faGroupWriteOnly,
-    faGroupReadWrite,
-    faGroupExecute,
-
-    // Others
-    faOthersReadOnly,
-    faOthersWriteOnly,
-    faOthersReadWrite,
-    faOthersExecute,
-
-    faHidden
-};
-
-#endif // FILEATTRIBUTE_H
--- a/src/jdk.jpackage/unix/native/libapplauncher/FileAttributes.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "FileAttributes.h"
-
-#include <algorithm>
-#include <list>
-#include <sys/stat.h>
-
-FileAttributes::FileAttributes(const TString FileName, bool FollowLink) {
-    FFileName = FileName;
-    FFollowLink = FollowLink;
-    ReadAttributes();
-}
-
-bool FileAttributes::WriteAttributes() {
-    bool result = false;
-
-    mode_t attributes = 0;
-
-    for (std::vector<FileAttribute>::const_iterator iterator =
-            FAttributes.begin();
-            iterator != FAttributes.end(); iterator++) {
-        switch (*iterator) {
-            case faBlockSpecial:
-            {
-                attributes |= S_IFBLK;
-                break;
-            }
-            case faCharacterSpecial:
-            {
-                attributes |= S_IFCHR;
-                break;
-            }
-            case faFIFOSpecial:
-            {
-                attributes |= S_IFIFO;
-                break;
-            }
-            case faNormal:
-            {
-                attributes |= S_IFREG;
-                break;
-            }
-            case faDirectory:
-            {
-                attributes |= S_IFDIR;
-                break;
-            }
-            case faSymbolicLink:
-            {
-                attributes |= S_IFLNK;
-                break;
-            }
-            case faSocket:
-            {
-                attributes |= S_IFSOCK;
-                break;
-            }
-
-                // Owner
-            case faReadOnly:
-            {
-                attributes |= S_IRUSR;
-                break;
-            }
-            case faWriteOnly:
-            {
-                attributes |= S_IWUSR;
-                break;
-            }
-            case faReadWrite:
-            {
-                attributes |= S_IRUSR;
-                attributes |= S_IWUSR;
-                break;
-            }
-            case faExecute:
-            {
-                attributes |= S_IXUSR;
-                break;
-            }
-
-                // Group
-            case faGroupReadOnly:
-            {
-                attributes |= S_IRGRP;
-                break;
-            }
-            case faGroupWriteOnly:
-            {
-                attributes |= S_IWGRP;
-                break;
-            }
-            case faGroupReadWrite:
-            {
-                attributes |= S_IRGRP;
-                attributes |= S_IWGRP;
-                break;
-            }
-            case faGroupExecute:
-            {
-                attributes |= S_IXGRP;
-                break;
-            }
-
-                // Others
-            case faOthersReadOnly:
-            {
-                attributes |= S_IROTH;
-                break;
-            }
-            case faOthersWriteOnly:
-            {
-                attributes |= S_IWOTH;
-                break;
-            }
-            case faOthersReadWrite:
-            {
-                attributes |= S_IROTH;
-                attributes |= S_IWOTH;
-                break;
-            }
-            case faOthersExecute:
-            {
-                attributes |= S_IXOTH;
-                break;
-            }
-            default:
-                break;
-        }
-    }
-
-    if (chmod(FFileName.data(), attributes) == 0) {
-        result = true;
-    }
-
-    return result;
-}
-
-#define S_ISRUSR(m)    (((m) & S_IRWXU) == S_IRUSR)
-#define S_ISWUSR(m)    (((m) & S_IRWXU) == S_IWUSR)
-#define S_ISXUSR(m)    (((m) & S_IRWXU) == S_IXUSR)
-
-#define S_ISRGRP(m)    (((m) & S_IRWXG) == S_IRGRP)
-#define S_ISWGRP(m)    (((m) & S_IRWXG) == S_IWGRP)
-#define S_ISXGRP(m)    (((m) & S_IRWXG) == S_IXGRP)
-
-#define S_ISROTH(m)    (((m) & S_IRWXO) == S_IROTH)
-#define S_ISWOTH(m)    (((m) & S_IRWXO) == S_IWOTH)
-#define S_ISXOTH(m)    (((m) & S_IRWXO) == S_IXOTH)
-
-bool FileAttributes::ReadAttributes() {
-    bool result = false;
-
-    struct stat status;
-
-    if (stat(StringToFileSystemString(FFileName), &status) == 0) {
-        result = true;
-
-        if (S_ISBLK(status.st_mode) != 0) {
-            FAttributes.push_back(faBlockSpecial);
-        }
-        if (S_ISCHR(status.st_mode) != 0) {
-            FAttributes.push_back(faCharacterSpecial);
-        }
-        if (S_ISFIFO(status.st_mode) != 0) {
-            FAttributes.push_back(faFIFOSpecial);
-        }
-        if (S_ISREG(status.st_mode) != 0) {
-            FAttributes.push_back(faNormal);
-        }
-        if (S_ISDIR(status.st_mode) != 0) {
-            FAttributes.push_back(faDirectory);
-        }
-        if (S_ISLNK(status.st_mode) != 0) {
-            FAttributes.push_back(faSymbolicLink);
-        }
-        if (S_ISSOCK(status.st_mode) != 0) {
-            FAttributes.push_back(faSocket);
-        }
-
-        // Owner
-        if (S_ISRUSR(status.st_mode) != 0) {
-            if (S_ISWUSR(status.st_mode) != 0) {
-                FAttributes.push_back(faReadWrite);
-            } else {
-                FAttributes.push_back(faReadOnly);
-            }
-        } else if (S_ISWUSR(status.st_mode) != 0) {
-            FAttributes.push_back(faWriteOnly);
-        }
-
-        if (S_ISXUSR(status.st_mode) != 0) {
-            FAttributes.push_back(faExecute);
-        }
-
-        // Group
-        if (S_ISRGRP(status.st_mode) != 0) {
-            if (S_ISWGRP(status.st_mode) != 0) {
-                FAttributes.push_back(faGroupReadWrite);
-            } else {
-                FAttributes.push_back(faGroupReadOnly);
-            }
-        } else if (S_ISWGRP(status.st_mode) != 0) {
-            FAttributes.push_back(faGroupWriteOnly);
-        }
-
-        if (S_ISXGRP(status.st_mode) != 0) {
-            FAttributes.push_back(faGroupExecute);
-        }
-
-
-        // Others
-        if (S_ISROTH(status.st_mode) != 0) {
-            if (S_ISWOTH(status.st_mode) != 0) {
-                FAttributes.push_back(faOthersReadWrite);
-            } else {
-                FAttributes.push_back(faOthersReadOnly);
-            }
-        } else if (S_ISWOTH(status.st_mode) != 0) {
-            FAttributes.push_back(faOthersWriteOnly);
-        }
-
-        if (S_ISXOTH(status.st_mode) != 0) {
-            FAttributes.push_back(faOthersExecute);
-        }
-
-        if (FFileName.size() > 0 && FFileName[0] == '.') {
-            FAttributes.push_back(faHidden);
-        }
-    }
-
-    return result;
-}
-
-bool FileAttributes::Valid(const FileAttribute Value) {
-    bool result = false;
-
-    switch (Value) {
-        case faReadWrite:
-        case faWriteOnly:
-        case faExecute:
-
-        case faGroupReadWrite:
-        case faGroupWriteOnly:
-        case faGroupReadOnly:
-        case faGroupExecute:
-
-        case faOthersReadWrite:
-        case faOthersWriteOnly:
-        case faOthersReadOnly:
-        case faOthersExecute:
-
-        case faReadOnly:
-            result = true;
-            break;
-
-        default:
-            break;
-    }
-
-    return result;
-}
-
-void FileAttributes::Append(FileAttribute Value) {
-    if (Valid(Value) == true) {
-        if ((Value == faReadOnly && Contains(faWriteOnly) == true) ||
-                (Value == faWriteOnly && Contains(faReadOnly) == true)) {
-            Value = faReadWrite;
-        }
-
-        FAttributes.push_back(Value);
-        WriteAttributes();
-    }
-}
-
-bool FileAttributes::Contains(FileAttribute Value) {
-    bool result = false;
-
-    std::vector<FileAttribute>::const_iterator iterator =
-            std::find(FAttributes.begin(), FAttributes.end(), Value);
-
-    if (iterator != FAttributes.end()) {
-        result = true;
-    }
-
-    return result;
-}
-
-void FileAttributes::Remove(FileAttribute Value) {
-    if (Valid(Value) == true) {
-        if (Value == faReadOnly && Contains(faReadWrite) == true) {
-            Append(faWriteOnly);
-            Remove(faReadWrite);
-        } else if (Value == faWriteOnly && Contains(faReadWrite) == true) {
-            Append(faReadOnly);
-            Remove(faReadWrite);
-        }
-
-        std::vector<FileAttribute>::iterator iterator =
-                std::find(FAttributes.begin(), FAttributes.end(), Value);
-
-        if (iterator != FAttributes.end()) {
-            FAttributes.erase(iterator);
-            WriteAttributes();
-        }
-    }
-}
--- a/src/jdk.jpackage/unix/native/libapplauncher/FilePath.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "PlatformDefs.h"
-#include "FilePath.h"
-
-#include <algorithm>
-#include <list>
-#include <sys/stat.h>
-
-bool FilePath::FileExists(const TString FileName) {
-    bool result = false;
-    struct stat buf;
-
-    if ((stat(StringToFileSystemString(FileName), &buf) == 0) &&
-            (S_ISREG(buf.st_mode) != 0)) {
-        result = true;
-    }
-
-    return result;
-}
-
-bool FilePath::DirectoryExists(const TString DirectoryName) {
-    bool result = false;
-
-    struct stat buf;
-
-    if ((stat(StringToFileSystemString(DirectoryName), &buf) == 0) &&
-            (S_ISDIR(buf.st_mode) != 0)) {
-        result = true;
-    }
-
-    return result;
-}
-
-bool FilePath::DeleteFile(const TString FileName) {
-    bool result = false;
-
-    if (FileExists(FileName) == true) {
-        if (unlink(StringToFileSystemString(FileName)) == 0) {
-            result = true;
-        }
-    }
-
-    return result;
-}
-
-bool FilePath::DeleteDirectory(const TString DirectoryName) {
-    bool result = false;
-
-    if (DirectoryExists(DirectoryName) == true) {
-        if (unlink(StringToFileSystemString(DirectoryName)) == 0) {
-            result = true;
-        }
-    }
-
-    return result;
-}
-
-TString FilePath::IncludeTrailingSeparator(const TString value) {
-    TString result = value;
-
-    if (value.size() > 0) {
-        TString::iterator i = result.end();
-        i--;
-
-        if (*i != TRAILING_PATHSEPARATOR) {
-            result += TRAILING_PATHSEPARATOR;
-        }
-    }
-
-    return result;
-}
-
-TString FilePath::IncludeTrailingSeparator(const char* value) {
-    TString lvalue = PlatformString(value).toString();
-    return IncludeTrailingSeparator(lvalue);
-}
-
-TString FilePath::IncludeTrailingSeparator(const wchar_t* value) {
-    TString lvalue = PlatformString(value).toString();
-    return IncludeTrailingSeparator(lvalue);
-}
-
-TString FilePath::ExtractFilePath(TString Path) {
-    return dirname(StringToFileSystemString(Path));
-}
-
-TString FilePath::ExtractFileExt(TString Path) {
-    TString result;
-    size_t dot = Path.find_last_of('.');
-
-    if (dot != TString::npos) {
-        result = Path.substr(dot, Path.size() - dot);
-    }
-
-    return result;
-}
-
-TString FilePath::ExtractFileName(TString Path) {
-    return basename(StringToFileSystemString(Path));
-}
-
-TString FilePath::ChangeFileExt(TString Path, TString Extension) {
-    TString result;
-    size_t dot = Path.find_last_of('.');
-
-    if (dot != TString::npos) {
-        result = Path.substr(0, dot) + Extension;
-    }
-
-    if (result.empty() == true) {
-        result = Path;
-    }
-
-    return result;
-}
-
-TString FilePath::FixPathForPlatform(TString Path) {
-    TString result = Path;
-    std::replace(result.begin(), result.end(),
-            BAD_TRAILING_PATHSEPARATOR, TRAILING_PATHSEPARATOR);
-    return result;
-}
-
-TString FilePath::FixPathSeparatorForPlatform(TString Path) {
-    TString result = Path;
-    std::replace(result.begin(), result.end(),
-            BAD_PATH_SEPARATOR, PATH_SEPARATOR);
-    return result;
-}
-
-TString FilePath::PathSeparator() {
-    TString result;
-    result = PATH_SEPARATOR;
-    return result;
-}
-
-bool FilePath::CreateDirectory(TString Path, bool ownerOnly) {
-    bool result = false;
-
-    std::list<TString> paths;
-    TString lpath = Path;
-
-    while (lpath.empty() == false && DirectoryExists(lpath) == false) {
-        paths.push_front(lpath);
-        lpath = ExtractFilePath(lpath);
-    }
-
-    for (std::list<TString>::iterator iterator = paths.begin();
-            iterator != paths.end(); iterator++) {
-        lpath = *iterator;
-
-        mode_t mode = S_IRWXU;
-        if (!ownerOnly) {
-            mode |= S_IRWXG | S_IROTH | S_IXOTH;
-        }
-        if (mkdir(StringToFileSystemString(lpath), mode) == 0) {
-            result = true;
-        } else {
-            result = false;
-            break;
-        }
-    }
-
-    return result;
-}
-
-void FilePath::ChangePermissions(TString FileName, bool ownerOnly) {
-    mode_t mode = S_IRWXU;
-    if (!ownerOnly) {
-        mode |= S_IRWXG | S_IROTH | S_IXOTH;
-    }
-    chmod(FileName.data(), mode);
-}
--- a/src/jdk.jpackage/unix/native/libapplauncher/PosixPlatform.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "PosixPlatform.h"
-
-#include "PlatformString.h"
-#include "FilePath.h"
-#include "Helpers.h"
-
-#include <assert.h>
-#include <stdbool.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/sysctl.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <limits.h>
-#include <pwd.h>
-#include <iostream>
-#include <algorithm>
-#include <dlfcn.h>
-#include <signal.h>
-
-using namespace std;
-
-PosixPlatform::PosixPlatform(void) {
-}
-
-PosixPlatform::~PosixPlatform(void) {
-}
-
-TString PosixPlatform::GetTempDirectory() {
-    struct passwd* pw = getpwuid(getuid());
-    TString homedir(pw->pw_dir);
-    homedir += getTmpDirString();
-    if (!FilePath::DirectoryExists(homedir)) {
-        if (!FilePath::CreateDirectory(homedir, false)) {
-            homedir.clear();
-        }
-    }
-
-    return homedir;
-}
-
-TString PosixPlatform::fixName(const TString& name) {
-    TString fixedName(name);
-    const TString chars("?:*<>/\\");
-    for (TString::const_iterator it = chars.begin(); it != chars.end(); it++) {
-        fixedName.erase(std::remove(fixedName.begin(),
-                fixedName.end(), *it), fixedName.end());
-    }
-    return fixedName;
-}
-
-MessageResponse PosixPlatform::ShowResponseMessage(TString title,
-        TString description) {
-    MessageResponse result = mrCancel;
-
-    printf("%s %s (Y/N)\n", PlatformString(title).toPlatformString(),
-            PlatformString(description).toPlatformString());
-    fflush(stdout);
-
-    std::string input;
-    std::cin >> input;
-
-    if (input == "Y") {
-        result = mrOK;
-    }
-
-    return result;
-}
-
-Module PosixPlatform::LoadLibrary(TString FileName) {
-    return dlopen(StringToFileSystemString(FileName), RTLD_LAZY);
-}
-
-void PosixPlatform::FreeLibrary(Module AModule) {
-    dlclose(AModule);
-}
-
-Procedure PosixPlatform::GetProcAddress(Module AModule,
-        std::string MethodName) {
-    return dlsym(AModule, PlatformString(MethodName));
-}
-
-Process* PosixPlatform::CreateProcess() {
-    return new PosixProcess();
-}
-
-void PosixPlatform::addPlatformDependencies(JavaLibrary *pJavaLibrary) {
-}
-
-void Platform::CopyString(char *Destination,
-        size_t NumberOfElements, const char *Source) {
-    strncpy(Destination, Source, NumberOfElements);
-
-    if (NumberOfElements > 0) {
-        Destination[NumberOfElements - 1] = '\0';
-    }
-}
-
-void Platform::CopyString(wchar_t *Destination,
-        size_t NumberOfElements, const wchar_t *Source) {
-    wcsncpy(Destination, Source, NumberOfElements);
-
-    if (NumberOfElements > 0) {
-        Destination[NumberOfElements - 1] = '\0';
-    }
-}
-
-// Owner must free the return value.
-
-MultibyteString Platform::WideStringToMultibyteString(
-        const wchar_t* value) {
-    MultibyteString result;
-    size_t count = 0;
-
-    if (value == NULL) {
-        return result;
-    }
-
-    count = wcstombs(NULL, value, 0);
-    if (count > 0) {
-        result.data = new char[count + 1];
-        result.data[count] = '\0';
-        result.length = count;
-        wcstombs(result.data, value, count);
-    }
-
-    return result;
-}
-
-// Owner must free the return value.
-
-WideString Platform::MultibyteStringToWideString(const char* value) {
-    WideString result;
-    size_t count = 0;
-
-    if (value == NULL) {
-        return result;
-    }
-
-    count = mbstowcs(NULL, value, 0);
-    if (count > 0) {
-        result.data = new wchar_t[count + 1];
-        result.data[count] = '\0';
-        result.length = count;
-        mbstowcs(result.data, value, count);
-    }
-
-    return result;
-}
-
-void PosixPlatform::InitStreamLocale(wios *stream) {
-    // Nothing to do for POSIX platforms.
-}
-
-PosixProcess::PosixProcess() : Process() {
-    FChildPID = 0;
-    FRunning = false;
-    FOutputHandle = 0;
-    FInputHandle = 0;
-}
-
-PosixProcess::~PosixProcess() {
-    Terminate();
-}
-
-bool PosixProcess::ReadOutput() {
-    bool result = false;
-
-    if (FOutputHandle != 0 && IsRunning() == true) {
-        char buffer[4096] = {0};
-
-        ssize_t count = read(FOutputHandle, buffer, sizeof (buffer));
-
-        if (count == -1) {
-            if (errno == EINTR) {
-                // continue;
-            } else {
-                perror("read");
-                exit(1);
-            }
-        } else if (count == 0) {
-            // break;
-        } else {
-            std::list<TString> output = Helpers::StringToArray(buffer);
-            FOutput.splice(FOutput.end(), output, output.begin(), output.end());
-            result = true;
-        }
-    }
-
-    return false;
-}
-
-bool PosixProcess::IsRunning() {
-    bool result = false;
-
-    if (kill(FChildPID, 0) == 0) {
-        result = true;
-    }
-
-    return result;
-}
-
-bool PosixProcess::Terminate() {
-    bool result = false;
-
-    if (IsRunning() == true && FRunning == true) {
-        FRunning = false;
-        Cleanup();
-        int status = kill(FChildPID, SIGTERM);
-
-        if (status == 0) {
-            result = true;
-        } else {
-#ifdef DEBUG
-            if (errno == EINVAL) {
-                printf("Kill error: The value of the sig argument is an invalid or unsupported signal number.");
-            } else if (errno == EPERM) {
-                printf("Kill error: The process does not have permission to send the signal to any receiving process.");
-            } else if (errno == ESRCH) {
-                printf("Kill error: No process or process group can be found corresponding to that specified by pid.");
-            }
-#endif // DEBUG
-            if (IsRunning() == true) {
-                status = kill(FChildPID, SIGKILL);
-
-                if (status == 0) {
-                    result = true;
-                }
-            }
-        }
-    }
-
-    return result;
-}
-
-bool PosixProcess::Wait() {
-    bool result = false;
-
-    int status = 0;
-    pid_t wpid = 0;
-
-    wpid = wait(&status);
-    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
-        if (errno != EINTR) {
-            status = -1;
-        }
-    }
-
-#ifdef DEBUG
-    if (WIFEXITED(status)) {
-        printf("child exited, status=%d\n", WEXITSTATUS(status));
-    } else if (WIFSIGNALED(status)) {
-        printf("child killed (signal %d)\n", WTERMSIG(status));
-    } else if (WIFSTOPPED(status)) {
-        printf("child stopped (signal %d)\n", WSTOPSIG(status));
-#ifdef WIFCONTINUED // Not all implementations support this
-    } else if (WIFCONTINUED(status)) {
-        printf("child continued\n");
-#endif // WIFCONTINUED
-    } else { // Non-standard case -- may never happen
-        printf("Unexpected status (0x%x)\n", status);
-    }
-#endif // DEBUG
-
-    if (wpid != -1) {
-        result = true;
-    }
-
-    return result;
-}
-
-TProcessID PosixProcess::GetProcessID() {
-    return FChildPID;
-}
-
-void PosixProcess::SetInput(TString Value) {
-    if (FInputHandle != 0) {
-        if (write(FInputHandle, Value.data(), Value.size()) < 0) {
-            throw Exception(_T("Internal Error - write failed"));
-        }
-    }
-}
-
-std::list<TString> PosixProcess::GetOutput() {
-    ReadOutput();
-    return Process::GetOutput();
-}
--- a/src/jdk.jpackage/unix/native/libapplauncher/PosixPlatform.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef POSIXPLATFORM_H
-#define POSIXPLATFORM_H
-
-#include "Platform.h"
-#include <signal.h>
-
-class PosixPlatform : virtual public Platform {
-protected:
-
-    TString fixName(const TString& name);
-
-    virtual TString getTmpDirString() = 0;
-
-public:
-    PosixPlatform(void);
-    virtual ~PosixPlatform(void);
-
-public:
-    virtual MessageResponse ShowResponseMessage(TString title,
-            TString description);
-
-    virtual Module LoadLibrary(TString FileName);
-    virtual void FreeLibrary(Module AModule);
-    virtual Procedure GetProcAddress(Module AModule, std::string MethodName);
-
-    virtual Process* CreateProcess();
-    virtual TString GetTempDirectory();
-    void InitStreamLocale(wios *stream);
-    void addPlatformDependencies(JavaLibrary *pJavaLibrary);
-};
-
-class PosixProcess : public Process {
-private:
-    pid_t FChildPID;
-    sigset_t saveblock;
-    int FOutputHandle;
-    int FInputHandle;
-    struct sigaction savintr, savequit;
-    bool FRunning;
-
-    void Cleanup();
-    bool ReadOutput();
-
-public:
-    PosixProcess();
-    virtual ~PosixProcess();
-
-    virtual bool IsRunning();
-    virtual bool Terminate();
-    virtual bool Execute(const TString Application,
-            const std::vector<TString> Arguments, bool AWait = false);
-    virtual bool Wait();
-    virtual TProcessID GetProcessID();
-    virtual void SetInput(TString Value);
-    virtual std::list<TString> GetOutput();
-};
-
-#endif // POSIXPLATFORM_H
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinAppBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.File;
-import java.nio.file.Path;
-import java.text.MessageFormat;
-import java.util.*;
-
-import static jdk.jpackage.internal.WindowsBundlerParam.*;
-
-public class WinAppBundler extends AbstractImageBundler {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.WinResources");
-
-    static final BundlerParamInfo<File> ICON_ICO =
-            new StandardBundlerParam<>(
-            "icon.ico",
-            File.class,
-            params -> {
-                File f = ICON.fetchFrom(params);
-                if (f != null && !f.getName().toLowerCase().endsWith(".ico")) {
-                    Log.error(MessageFormat.format(
-                            I18N.getString("message.icon-not-ico"), f));
-                    return null;
-                }
-                return f;
-            },
-            (s, p) -> new File(s));
-
-    @Override
-    public boolean validate(Map<String, ? super Object> params)
-            throws ConfigException {
-        try {
-            Objects.requireNonNull(params);
-            return doValidate(params);
-        } catch (RuntimeException re) {
-            if (re.getCause() instanceof ConfigException) {
-                throw (ConfigException) re.getCause();
-            } else {
-                throw new ConfigException(re);
-            }
-        }
-    }
-
-    // to be used by chained bundlers, e.g. by EXE bundler to avoid
-    // skipping validation if p.type does not include "image"
-    private boolean doValidate(Map<String, ? super Object> p)
-            throws ConfigException {
-
-        imageBundleValidation(p);
-        return true;
-    }
-
-    public boolean bundle(Map<String, ? super Object> p, File outputDirectory)
-            throws PackagerException {
-        return doBundle(p, outputDirectory, false) != null;
-    }
-
-    File doBundle(Map<String, ? super Object> p, File outputDirectory,
-            boolean dependentTask) throws PackagerException {
-        if (StandardBundlerParam.isRuntimeInstaller(p)) {
-            return PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
-        } else {
-            return doAppBundle(p, outputDirectory, dependentTask);
-        }
-    }
-
-    File doAppBundle(Map<String, ? super Object> p, File outputDirectory,
-            boolean dependentTask) throws PackagerException {
-        try {
-            File rootDirectory = createRoot(p, outputDirectory, dependentTask,
-                    APP_NAME.fetchFrom(p));
-            AbstractAppImageBuilder appBuilder =
-                    new WindowsAppImageBuilder(p, outputDirectory.toPath());
-            if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {
-                JLinkBundlerHelper.execute(p, appBuilder);
-            } else {
-                StandardBundlerParam.copyPredefinedRuntimeImage(p, appBuilder);
-            }
-            if (!dependentTask) {
-                Log.verbose(MessageFormat.format(
-                        I18N.getString("message.result-dir"),
-                        outputDirectory.getAbsolutePath()));
-            }
-            return rootDirectory;
-        } catch (PackagerException pe) {
-            throw pe;
-        } catch (Exception e) {
-            Log.verbose(e);
-            throw new PackagerException(e);
-        }
-    }
-
-    @Override
-    public String getName() {
-        return I18N.getString("app.bundler.name");
-    }
-
-    @Override
-    public String getID() {
-        return "windows.app";
-    }
-
-    @Override
-    public String getBundleType() {
-        return "IMAGE";
-    }
-
-    @Override
-    public File execute(Map<String, ? super Object> params,
-            File outputParentDir) throws PackagerException {
-        return doBundle(params, outputParentDir, false);
-    }
-
-    @Override
-    public boolean supported(boolean platformInstaller) {
-        return true;
-    }
-
-    @Override
-    public boolean isDefault() {
-        return false;
-    }
-
-}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2017, 2019, 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.*;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.text.MessageFormat;
-import java.util.*;
-
-public class WinExeBundler extends AbstractBundler {
-
-    static {
-        System.loadLibrary("jpackage");
-    }
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.WinResources");
-
-    public static final BundlerParamInfo<WinAppBundler> APP_BUNDLER
-            = new WindowsBundlerParam<>(
-                    "win.app.bundler",
-                    WinAppBundler.class,
-                    params -> new WinAppBundler(),
-                    null);
-
-    public static final BundlerParamInfo<File> EXE_IMAGE_DIR
-            = new WindowsBundlerParam<>(
-                    "win.exe.imageDir",
-                    File.class,
-                    params -> {
-                        File imagesRoot = IMAGES_ROOT.fetchFrom(params);
-                        if (!imagesRoot.exists()) {
-                            imagesRoot.mkdirs();
-                        }
-                        return new File(imagesRoot, "win-exe.image");
-                    },
-                    (s, p) -> null);
-
-    private final static String EXE_WRAPPER_NAME = "msiwrapper.exe";
-
-    @Override
-    public String getName() {
-        return getString("exe.bundler.name");
-    }
-
-    @Override
-    public String getID() {
-        return "exe";
-    }
-
-    @Override
-    public String getBundleType() {
-        return "INSTALLER";
-    }
-
-    @Override
-    public File execute(Map<String, ? super Object> params,
-            File outputParentDir) throws PackagerException {
-        return bundle(params, outputParentDir);
-    }
-
-    @Override
-    public boolean supported(boolean platformInstaller) {
-        return msiBundler.supported(platformInstaller);
-    }
-
-    @Override
-    public boolean isDefault() {
-        return true;
-    }
-
-    @Override
-    public boolean validate(Map<String, ? super Object> params)
-            throws ConfigException {
-        return msiBundler.validate(params);
-    }
-
-    public File bundle(Map<String, ? super Object> params, File outdir)
-            throws PackagerException {
-
-        IOUtils.writableOutputDir(outdir.toPath());
-
-        File exeImageDir = EXE_IMAGE_DIR.fetchFrom(params);
-
-        // Write msi to temporary directory.
-        File msi = msiBundler.bundle(params, exeImageDir);
-
-        try {
-            new ScriptRunner()
-            .setDirectory(msi.toPath().getParent())
-            .setResourceCategoryId("resource.post-msi-script")
-            .setScriptNameSuffix("post-msi")
-            .setEnvironmentVariable("JpMsiFile", msi.getAbsolutePath().toString())
-            .run(params);
-
-            return buildEXE(msi, outdir);
-        } catch (IOException ex) {
-            Log.verbose(ex);
-            throw new PackagerException(ex);
-        }
-    }
-
-    private File buildEXE(File msi, File outdir)
-            throws IOException {
-
-        Log.verbose(MessageFormat.format(
-                getString("message.outputting-to-location"),
-                outdir.getAbsolutePath()));
-
-        // Copy template msi wrapper next to msi file
-        String exePath = msi.getAbsolutePath();
-        exePath = exePath.substring(0, exePath.lastIndexOf('.')) + ".exe";
-        try (InputStream is = OverridableResource.readDefault(EXE_WRAPPER_NAME)) {
-            Files.copy(is, Path.of(exePath));
-        }
-        // Embed msi in msi wrapper exe.
-        embedMSI(exePath, msi.getAbsolutePath());
-
-        Path dstExePath = Paths.get(outdir.getAbsolutePath(),
-                Path.of(exePath).getFileName().toString());
-        Files.deleteIfExists(dstExePath);
-
-        Files.copy(Path.of(exePath), dstExePath);
-
-        Log.verbose(MessageFormat.format(
-                getString("message.output-location"),
-                outdir.getAbsolutePath()));
-
-        return dstExePath.toFile();
-    }
-
-    private static String getString(String key)
-            throws MissingResourceException {
-        return I18N.getString(key);
-    }
-
-    private final WinMsiBundler msiBundler = new WinMsiBundler();
-
-    private static native int embedMSI(String exePath, String msiPath);
-}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,580 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.*;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-import static jdk.jpackage.internal.WindowsBundlerParam.*;
-
-/**
- * WinMsiBundler
- *
- * Produces .msi installer from application image. Uses WiX Toolkit to build
- * .msi installer.
- * <p>
- * {@link #execute} method creates a number of source files with the description
- * of installer to be processed by WiX tools. Generated source files are stored
- * in "config" subdirectory next to "app" subdirectory in the root work
- * directory. The following WiX source files are generated:
- * <ul>
- * <li>main.wxs. Main source file with the installer description
- * <li>bundle.wxf. Source file with application and Java run-time directory tree
- * description.
- * </ul>
- * <p>
- * main.wxs file is a copy of main.wxs resource from
- * jdk.jpackage.internal.resources package. It is parametrized with the
- * following WiX variables:
- * <ul>
- * <li>JpAppName. Name of the application. Set to the value of --name command
- * line option
- * <li>JpAppVersion. Version of the application. Set to the value of
- * --app-version command line option
- * <li>JpAppVendor. Vendor of the application. Set to the value of --vendor
- * command line option
- * <li>JpAppDescription. Description of the application. Set to the value of
- * --description command line option
- * <li>JpProductCode. Set to product code UUID of the application. Random value
- * generated by jpackage every time {@link #execute} method is called
- * <li>JpProductUpgradeCode. Set to upgrade code UUID of the application. Random
- * value generated by jpackage every time {@link #execute} method is called if
- * --win-upgrade-uuid command line option is not specified. Otherwise this
- * 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>
- */
-public class WinMsiBundler  extends AbstractBundler {
-
-    public static final BundlerParamInfo<WinAppBundler> APP_BUNDLER =
-            new WindowsBundlerParam<>(
-            "win.app.bundler",
-            WinAppBundler.class,
-            params -> new WinAppBundler(),
-            null);
-
-    public static final BundlerParamInfo<File> MSI_IMAGE_DIR =
-            new WindowsBundlerParam<>(
-            "win.msi.imageDir",
-            File.class,
-            params -> {
-                File imagesRoot = IMAGES_ROOT.fetchFrom(params);
-                if (!imagesRoot.exists()) imagesRoot.mkdirs();
-                return new File(imagesRoot, "win-msi.image");
-            },
-            (s, p) -> null);
-
-    public static final BundlerParamInfo<File> WIN_APP_IMAGE =
-            new WindowsBundlerParam<>(
-            "win.app.image",
-            File.class,
-            null,
-            (s, p) -> null);
-
-    public static final StandardBundlerParam<Boolean> MSI_SYSTEM_WIDE  =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.WIN_PER_USER_INSTALLATION.getId(),
-                    Boolean.class,
-                    params -> true, // MSIs default to system wide
-                    // valueOf(null) is false,
-                    // and we actually do want null
-                    (s, p) -> (s == null || "null".equalsIgnoreCase(s))? null
-                            : Boolean.valueOf(s)
-            );
-
-
-    public static final StandardBundlerParam<String> PRODUCT_VERSION =
-            new StandardBundlerParam<>(
-                    "win.msi.productVersion",
-                    String.class,
-                    VERSION::fetchFrom,
-                    (s, p) -> s
-            );
-
-    private static final BundlerParamInfo<String> UPGRADE_UUID =
-            new WindowsBundlerParam<>(
-            Arguments.CLIOptions.WIN_UPGRADE_UUID.getId(),
-            String.class,
-            null,
-            (s, p) -> s);
-
-    @Override
-    public String getName() {
-        return I18N.getString("msi.bundler.name");
-    }
-
-    @Override
-    public String getID() {
-        return "msi";
-    }
-
-    @Override
-    public String getBundleType() {
-        return "INSTALLER";
-    }
-
-    @Override
-    public File execute(Map<String, ? super Object> params,
-            File outputParentDir) throws PackagerException {
-        return bundle(params, outputParentDir);
-    }
-
-    @Override
-    public boolean supported(boolean platformInstaller) {
-        try {
-            if (wixToolset == null) {
-                wixToolset = WixTool.toolset();
-            }
-            return true;
-        } catch (ConfigException ce) {
-            Log.error(ce.getMessage());
-            if (ce.getAdvice() != null) {
-                Log.error(ce.getAdvice());
-            }
-        } catch (Exception e) {
-            Log.error(e.getMessage());
-        }
-        return false;
-    }
-
-    @Override
-    public boolean isDefault() {
-        return false;
-    }
-
-    private static UUID getUpgradeCode(Map<String, ? super Object> params) {
-        String upgradeCode = UPGRADE_UUID.fetchFrom(params);
-        if (upgradeCode != null) {
-            return UUID.fromString(upgradeCode);
-        }
-        return createNameUUID("UpgradeCode", params, List.of(VENDOR, APP_NAME));
-    }
-
-    private static UUID getProductCode(Map<String, ? super Object> params) {
-        return createNameUUID("ProductCode", params, List.of(VENDOR, APP_NAME,
-                VERSION));
-    }
-
-    private static UUID createNameUUID(String prefix,
-            Map<String, ? super Object> params,
-            List<StandardBundlerParam<String>> components) {
-        String key = Stream.concat(Stream.of(prefix), components.stream().map(
-                c -> c.fetchFrom(params))).collect(Collectors.joining("/"));
-        return UUID.nameUUIDFromBytes(key.getBytes(StandardCharsets.UTF_8));
-    }
-
-    @Override
-    public boolean validate(Map<String, ? super Object> params)
-            throws ConfigException {
-        try {
-            if (wixToolset == null) {
-                wixToolset = WixTool.toolset();
-            }
-
-            try {
-                getUpgradeCode(params);
-            } catch (IllegalArgumentException ex) {
-                throw new ConfigException(ex);
-            }
-
-            for (var toolInfo: wixToolset.values()) {
-                Log.verbose(MessageFormat.format(I18N.getString(
-                        "message.tool-version"), toolInfo.path.getFileName(),
-                        toolInfo.version));
-            }
-
-            wixSourcesBuilder.setWixVersion(wixToolset.get(WixTool.Light).version);
-
-            wixSourcesBuilder.logWixFeatures();
-
-            /********* validate bundle parameters *************/
-
-            String version = PRODUCT_VERSION.fetchFrom(params);
-            if (!isVersionStringValid(version)) {
-                throw new ConfigException(
-                        MessageFormat.format(I18N.getString(
-                                "error.version-string-wrong-format"), version),
-                        MessageFormat.format(I18N.getString(
-                                "error.version-string-wrong-format.advice"),
-                                PRODUCT_VERSION.getID()));
-            }
-
-            // only one mime type per association, at least one file extension
-            List<Map<String, ? super Object>> associations =
-                    FILE_ASSOCIATIONS.fetchFrom(params);
-            if (associations != null) {
-                for (int i = 0; i < associations.size(); i++) {
-                    Map<String, ? super Object> assoc = associations.get(i);
-                    List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc);
-                    if (mimes.size() > 1) {
-                        throw new ConfigException(MessageFormat.format(
-                                I18N.getString("error.too-many-content-types-for-file-association"), i),
-                                I18N.getString("error.too-many-content-types-for-file-association.advice"));
-                    }
-                }
-            }
-
-            return true;
-        } catch (RuntimeException re) {
-            if (re.getCause() instanceof ConfigException) {
-                throw (ConfigException) re.getCause();
-            } else {
-                throw new ConfigException(re);
-            }
-        }
-    }
-
-    // https://msdn.microsoft.com/en-us/library/aa370859%28v=VS.85%29.aspx
-    // The format of the string is as follows:
-    //     major.minor.build
-    // The first field is the major version and has a maximum value of 255.
-    // The second field is the minor version and has a maximum value of 255.
-    // The third field is called the build version or the update version and
-    // has a maximum value of 65,535.
-    static boolean isVersionStringValid(String v) {
-        if (v == null) {
-            return true;
-        }
-
-        String p[] = v.split("\\.");
-        if (p.length > 3) {
-            Log.verbose(I18N.getString(
-                    "message.version-string-too-many-components"));
-            return false;
-        }
-
-        try {
-            int val = Integer.parseInt(p[0]);
-            if (val < 0 || val > 255) {
-                Log.verbose(I18N.getString(
-                        "error.version-string-major-out-of-range"));
-                return false;
-            }
-            if (p.length > 1) {
-                val = Integer.parseInt(p[1]);
-                if (val < 0 || val > 255) {
-                    Log.verbose(I18N.getString(
-                            "error.version-string-minor-out-of-range"));
-                    return false;
-                }
-            }
-            if (p.length > 2) {
-                val = Integer.parseInt(p[2]);
-                if (val < 0 || val > 65535) {
-                    Log.verbose(I18N.getString(
-                            "error.version-string-build-out-of-range"));
-                    return false;
-                }
-            }
-        } catch (NumberFormatException ne) {
-            Log.verbose(I18N.getString("error.version-string-part-not-number"));
-            Log.verbose(ne);
-            return false;
-        }
-
-        return true;
-    }
-
-    private void prepareProto(Map<String, ? super Object> params)
-                throws PackagerException, IOException {
-        File appImage = StandardBundlerParam.getPredefinedAppImage(params);
-        File appDir = null;
-
-        // we either have an application image or need to build one
-        if (appImage != null) {
-            appDir = new File(MSI_IMAGE_DIR.fetchFrom(params),
-                    APP_NAME.fetchFrom(params));
-            // copy everything from appImage dir into appDir/name
-            IOUtils.copyRecursive(appImage.toPath(), appDir.toPath());
-        } else {
-            appDir = APP_BUNDLER.fetchFrom(params).doBundle(params,
-                    MSI_IMAGE_DIR.fetchFrom(params), true);
-        }
-
-        params.put(WIN_APP_IMAGE.getID(), appDir);
-
-        String licenseFile = LICENSE_FILE.fetchFrom(params);
-        if (licenseFile != null) {
-            // need to copy license file to the working directory
-            // and convert to rtf if needed
-            File lfile = new File(licenseFile);
-            File destFile = new File(CONFIG_ROOT.fetchFrom(params),
-                    lfile.getName());
-
-            IOUtils.copyFile(lfile, destFile);
-            destFile.setWritable(true);
-            ensureByMutationFileIsRTF(destFile);
-        }
-    }
-
-    public File bundle(Map<String, ? super Object> params, File outdir)
-            throws PackagerException {
-
-        IOUtils.writableOutputDir(outdir.toPath());
-
-        Path imageDir = MSI_IMAGE_DIR.fetchFrom(params).toPath();
-        try {
-            Files.createDirectories(imageDir);
-
-            prepareProto(params);
-
-            wixSourcesBuilder
-            .initFromParams(WIN_APP_IMAGE.fetchFrom(params).toPath(), params)
-            .createMainFragment(CONFIG_ROOT.fetchFrom(params).toPath().resolve(
-                    "bundle.wxf"));
-
-            Map<String, String> wixVars = prepareMainProjectFile(params);
-
-            new ScriptRunner()
-            .setDirectory(imageDir)
-            .setResourceCategoryId("resource.post-app-image-script")
-            .setScriptNameSuffix("post-image")
-            .setEnvironmentVariable("JpAppImageDir", imageDir.toAbsolutePath().toString())
-            .run(params);
-
-            return buildMSI(params, wixVars, outdir);
-        } catch (IOException ex) {
-            Log.verbose(ex);
-            throw new PackagerException(ex);
-        }
-    }
-
-    Map<String, String> prepareMainProjectFile(
-            Map<String, ? super Object> params) throws IOException {
-        Map<String, String> data = new HashMap<>();
-
-        final UUID productCode = getProductCode(params);
-        final UUID upgradeCode = getUpgradeCode(params);
-
-        data.put("JpProductCode", productCode.toString());
-        data.put("JpProductUpgradeCode", upgradeCode.toString());
-
-        Log.verbose(MessageFormat.format(I18N.getString("message.product-code"),
-                productCode));
-        Log.verbose(MessageFormat.format(I18N.getString("message.upgrade-code"),
-                upgradeCode));
-
-        data.put("JpAllowUpgrades", "yes");
-
-        data.put("JpAppName", APP_NAME.fetchFrom(params));
-        data.put("JpAppDescription", DESCRIPTION.fetchFrom(params));
-        data.put("JpAppVendor", VENDOR.fetchFrom(params));
-        data.put("JpAppVersion", PRODUCT_VERSION.fetchFrom(params));
-
-        final Path configDir = CONFIG_ROOT.fetchFrom(params).toPath();
-
-        data.put("JpConfigDir", configDir.toAbsolutePath().toString());
-
-        if (MSI_SYSTEM_WIDE.fetchFrom(params)) {
-            data.put("JpIsSystemWide", "yes");
-        }
-
-        String licenseFile = LICENSE_FILE.fetchFrom(params);
-        if (licenseFile != null) {
-            String lname = new File(licenseFile).getName();
-            File destFile = new File(CONFIG_ROOT.fetchFrom(params), lname);
-            data.put("JpLicenseRtf", destFile.getAbsolutePath());
-        }
-
-        // 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, Paths.get(
-                        CONFIG_ROOT.fetchFrom(params).getAbsolutePath(),
-                        fname));
-            }
-        }
-
-        // Copy l10n files.
-        for (String loc : Arrays.asList("en", "ja", "zh_CN")) {
-            String fname = "MsiInstallerStrings_" + loc + ".wxl";
-            try (InputStream is = OverridableResource.readDefault(fname)) {
-                Files.copy(is, Paths.get(
-                        CONFIG_ROOT.fetchFrom(params).getAbsolutePath(),
-                        fname));
-            }
-        }
-
-        createResource("main.wxs", params)
-                .setCategory(I18N.getString("resource.main-wix-file"))
-                .saveToFile(configDir.resolve("main.wxs"));
-
-        createResource("overrides.wxi", params)
-                .setCategory(I18N.getString("resource.overrides-wix-file"))
-                .saveToFile(configDir.resolve("overrides.wxi"));
-
-        return data;
-    }
-
-    private File buildMSI(Map<String, ? super Object> params,
-            Map<String, String> wixVars, File outdir)
-            throws IOException {
-
-        File msiOut = new File(
-                outdir, INSTALLER_FILE_NAME.fetchFrom(params) + ".msi");
-
-        Log.verbose(MessageFormat.format(I18N.getString(
-                "message.preparing-msi-config"), msiOut.getAbsolutePath()));
-
-        WixPipeline wixPipeline = new WixPipeline()
-        .setToolset(wixToolset.entrySet().stream().collect(
-                Collectors.toMap(
-                        entry -> entry.getKey(),
-                        entry -> entry.getValue().path)))
-        .setWixObjDir(TEMP_ROOT.fetchFrom(params).toPath().resolve("wixobj"))
-        .setWorkDir(WIN_APP_IMAGE.fetchFrom(params).toPath())
-        .addSource(CONFIG_ROOT.fetchFrom(params).toPath().resolve("main.wxs"), wixVars)
-        .addSource(CONFIG_ROOT.fetchFrom(params).toPath().resolve("bundle.wxf"), null);
-
-        Log.verbose(MessageFormat.format(I18N.getString(
-                "message.generating-msi"), msiOut.getAbsolutePath()));
-
-        boolean enableLicenseUI = (LICENSE_FILE.fetchFrom(params) != null);
-        boolean enableInstalldirUI = INSTALLDIR_CHOOSER.fetchFrom(params);
-
-        List<String> lightArgs = new ArrayList<>();
-
-        if (!MSI_SYSTEM_WIDE.fetchFrom(params)) {
-            wixPipeline.addLightOptions("-sice:ICE91");
-        }
-        if (enableLicenseUI || enableInstalldirUI) {
-            wixPipeline.addLightOptions("-ext", "WixUIExtension");
-        }
-
-        wixPipeline.addLightOptions("-loc",
-                CONFIG_ROOT.fetchFrom(params).toPath().resolve(I18N.getString(
-                        "resource.wxl-file-name")).toAbsolutePath().toString());
-
-        // Only needed if we using CA dll, so Wix can find it
-        if (enableInstalldirUI) {
-            wixPipeline.addLightOptions("-b", CONFIG_ROOT.fetchFrom(params).getAbsolutePath());
-        }
-
-        wixPipeline.buildMsi(msiOut.toPath().toAbsolutePath());
-
-        return msiOut;
-    }
-
-    public static void ensureByMutationFileIsRTF(File f) {
-        if (f == null || !f.isFile()) return;
-
-        try {
-            boolean existingLicenseIsRTF = false;
-
-            try (FileInputStream fin = new FileInputStream(f)) {
-                byte[] firstBits = new byte[7];
-
-                if (fin.read(firstBits) == firstBits.length) {
-                    String header = new String(firstBits);
-                    existingLicenseIsRTF = "{\\rtf1\\".equals(header);
-                }
-            }
-
-            if (!existingLicenseIsRTF) {
-                List<String> oldLicense = Files.readAllLines(f.toPath());
-                try (Writer w = Files.newBufferedWriter(
-                        f.toPath(), Charset.forName("Windows-1252"))) {
-                    w.write("{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033"
-                            + "{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}}\n"
-                            + "\\viewkind4\\uc1\\pard\\sa200\\sl276"
-                            + "\\slmult1\\lang9\\fs20 ");
-                    oldLicense.forEach(l -> {
-                        try {
-                            for (char c : l.toCharArray()) {
-                                // 0x00 <= ch < 0x20 Escaped (\'hh)
-                                // 0x20 <= ch < 0x80 Raw(non - escaped) char
-                                // 0x80 <= ch <= 0xFF Escaped(\ 'hh)
-                                // 0x5C, 0x7B, 0x7D (special RTF characters
-                                // \,{,})Escaped(\'hh)
-                                // ch > 0xff Escaped (\\ud###?)
-                                if (c < 0x10) {
-                                    w.write("\\'0");
-                                    w.write(Integer.toHexString(c));
-                                } else if (c > 0xff) {
-                                    w.write("\\ud");
-                                    w.write(Integer.toString(c));
-                                    // \\uc1 is in the header and in effect
-                                    // so we trail with a replacement char if
-                                    // the font lacks that character - '?'
-                                    w.write("?");
-                                } else if ((c < 0x20) || (c >= 0x80) ||
-                                        (c == 0x5C) || (c == 0x7B) ||
-                                        (c == 0x7D)) {
-                                    w.write("\\'");
-                                    w.write(Integer.toHexString(c));
-                                } else {
-                                    w.write(c);
-                                }
-                            }
-                            // blank lines are interpreted as paragraph breaks
-                            if (l.length() < 1) {
-                                w.write("\\par");
-                            } else {
-                                w.write(" ");
-                            }
-                            w.write("\r\n");
-                        } catch (IOException e) {
-                            Log.verbose(e);
-                        }
-                    });
-                    w.write("}\r\n");
-                }
-            }
-        } catch (IOException e) {
-            Log.verbose(e);
-        }
-
-    }
-
-    private Map<WixTool, WixTool.ToolInfo> wixToolset;
-    private WixSourcesBuilder wixSourcesBuilder = new WixSourcesBuilder();
-
-}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsAppImageBuilder.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,367 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.UncheckedIOException;
-import java.io.Writer;
-import java.io.BufferedWriter;
-import java.io.FileWriter;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.nio.file.attribute.PosixFilePermission;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.ResourceBundle;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-import static jdk.jpackage.internal.OverridableResource.createResource;
-
-import static jdk.jpackage.internal.StandardBundlerParam.*;
-
-public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
-
-    static {
-        System.loadLibrary("jpackage");
-    }
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.WinResources");
-
-    private final static String LIBRARY_NAME = "applauncher.dll";
-    private final static String REDIST_MSVCR = "vcruntimeVS_VER.dll";
-    private final static String REDIST_MSVCP = "msvcpVS_VER.dll";
-
-    private final static String TEMPLATE_APP_ICON ="java48.ico";
-
-    private static final String EXECUTABLE_PROPERTIES_TEMPLATE =
-            "WinLauncher.template";
-
-    private final Path root;
-    private final Path appDir;
-    private final Path appModsDir;
-    private final Path runtimeDir;
-    private final Path mdir;
-    private final Path binDir;
-
-    public static final BundlerParamInfo<Boolean> REBRAND_EXECUTABLE =
-            new WindowsBundlerParam<>(
-            "win.launcher.rebrand",
-            Boolean.class,
-            params -> Boolean.TRUE,
-            (s, p) -> Boolean.valueOf(s));
-
-    public static final BundlerParamInfo<File> ICON_ICO =
-            new StandardBundlerParam<>(
-            "icon.ico",
-            File.class,
-            params -> {
-                File f = ICON.fetchFrom(params);
-                if (f != null && !f.getName().toLowerCase().endsWith(".ico")) {
-                    Log.error(MessageFormat.format(
-                            I18N.getString("message.icon-not-ico"), f));
-                    return null;
-                }
-                return f;
-            },
-            (s, p) -> new File(s));
-
-    public static final StandardBundlerParam<Boolean> CONSOLE_HINT =
-            new WindowsBundlerParam<>(
-            Arguments.CLIOptions.WIN_CONSOLE_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));
-
-    public WindowsAppImageBuilder(Map<String, Object> params, Path imageOutDir)
-            throws IOException {
-        super(params,
-                imageOutDir.resolve(APP_NAME.fetchFrom(params) + "/runtime"));
-
-        Objects.requireNonNull(imageOutDir);
-
-        this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params));
-        this.appDir = root.resolve("app");
-        this.appModsDir = appDir.resolve("mods");
-        this.runtimeDir = root.resolve("runtime");
-        this.mdir = runtimeDir.resolve("lib");
-        this.binDir = root;
-        Files.createDirectories(appDir);
-        Files.createDirectories(runtimeDir);
-    }
-
-    private void writeEntry(InputStream in, Path dstFile) throws IOException {
-        Files.createDirectories(dstFile.getParent());
-        Files.copy(in, dstFile);
-    }
-
-    private static String getLauncherName(Map<String, ? super Object> params) {
-        return APP_NAME.fetchFrom(params) + ".exe";
-    }
-
-    // Returns launcher resource name for launcher we need to use.
-    public static String getLauncherResourceName(
-            Map<String, ? super Object> params) {
-        if (CONSOLE_HINT.fetchFrom(params)) {
-            return "jpackageapplauncher.exe";
-        } else {
-            return "jpackageapplauncherw.exe";
-        }
-    }
-
-    public static String getLauncherCfgName(
-            Map<String, ? super Object> params) {
-        return "app/" + APP_NAME.fetchFrom(params) +".cfg";
-    }
-
-    private File getConfig_AppIcon(Map<String, ? super Object> params) {
-        return new File(getConfigRoot(params),
-                APP_NAME.fetchFrom(params) + ".ico");
-    }
-
-    private File getConfig_ExecutableProperties(
-           Map<String, ? super Object> params) {
-        return new File(getConfigRoot(params),
-                APP_NAME.fetchFrom(params) + ".properties");
-    }
-
-    File getConfigRoot(Map<String, ? super Object> params) {
-        return CONFIG_ROOT.fetchFrom(params);
-    }
-
-    @Override
-    public Path getAppDir() {
-        return appDir;
-    }
-
-    @Override
-    public Path getAppModsDir() {
-        return appModsDir;
-    }
-
-    @Override
-    public void prepareApplicationFiles(Map<String, ? super Object> params)
-            throws IOException {
-        Map<String, ? super Object> originalParams = new HashMap<>(params);
-
-        try {
-            IOUtils.writableOutputDir(root);
-            IOUtils.writableOutputDir(binDir);
-        } catch (PackagerException pe) {
-            throw new RuntimeException(pe);
-        }
-        AppImageFile.save(root, params);
-
-        // create the .exe launchers
-        createLauncherForEntryPoint(params);
-
-        // copy the jars
-        copyApplication(params);
-
-        // copy in the needed libraries
-        try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
-            Files.copy(is_lib, binDir.resolve(LIBRARY_NAME));
-        }
-
-        copyMSVCDLLs();
-
-        // create the additional launcher(s), if any
-        List<Map<String, ? super Object>> entryPoints =
-                StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
-        for (Map<String, ? super Object> entryPoint : entryPoints) {
-            createLauncherForEntryPoint(
-                    AddLauncherArguments.merge(originalParams, entryPoint));
-        }
-    }
-
-    @Override
-    public void prepareJreFiles(Map<String, ? super Object> params)
-        throws IOException {}
-
-    private void copyMSVCDLLs() throws IOException {
-        AtomicReference<IOException> ioe = new AtomicReference<>();
-        try (Stream<Path> files = Files.list(runtimeDir.resolve("bin"))) {
-            files.filter(p -> Pattern.matches(
-                    "^(vcruntime|msvcp|msvcr|ucrtbase|api-ms-win-).*\\.dll$",
-                    p.toFile().getName().toLowerCase()))
-                 .forEach(p -> {
-                    try {
-                        Files.copy(p, binDir.resolve((p.toFile().getName())));
-                    } catch (IOException e) {
-                        ioe.set(e);
-                    }
-                });
-        }
-
-        IOException e = ioe.get();
-        if (e != null) {
-            throw e;
-        }
-    }
-
-    private void validateValueAndPut(
-            Map<String, String> data, String key,
-            BundlerParamInfo<String> param,
-            Map<String, ? super Object> params) {
-        String value = param.fetchFrom(params);
-        if (value.contains("\r") || value.contains("\n")) {
-            Log.error("Configuration Parameter " + param.getID()
-                    + " contains multiple lines of text, ignore it");
-            data.put(key, "");
-            return;
-        }
-        data.put(key, value);
-    }
-
-    protected void prepareExecutableProperties(
-           Map<String, ? super Object> params) throws IOException {
-
-        Map<String, String> data = new HashMap<>();
-
-        // mapping Java parameters in strings for version resource
-        validateValueAndPut(data, "COMPANY_NAME", VENDOR, params);
-        validateValueAndPut(data, "FILE_DESCRIPTION", DESCRIPTION, params);
-        validateValueAndPut(data, "FILE_VERSION", VERSION, params);
-        data.put("INTERNAL_NAME", getLauncherName(params));
-        validateValueAndPut(data, "LEGAL_COPYRIGHT", COPYRIGHT, params);
-        data.put("ORIGINAL_FILENAME", getLauncherName(params));
-        validateValueAndPut(data, "PRODUCT_NAME", APP_NAME, params);
-        validateValueAndPut(data, "PRODUCT_VERSION", VERSION, params);
-
-        createResource(EXECUTABLE_PROPERTIES_TEMPLATE, params)
-                .setCategory(I18N.getString("resource.executable-properties-template"))
-                .setSubstitutionData(data)
-                .saveToFile(getConfig_ExecutableProperties(params));
-    }
-
-    private void createLauncherForEntryPoint(
-            Map<String, ? super Object> params) throws IOException {
-
-        File iconTarget = getConfig_AppIcon(params);
-
-        createResource(TEMPLATE_APP_ICON, params)
-                .setCategory("icon")
-                .setExternal(ICON_ICO.fetchFrom(params))
-                .saveToFile(iconTarget);
-
-        writeCfgFile(params, root.resolve(
-                getLauncherCfgName(params)).toFile());
-
-        prepareExecutableProperties(params);
-
-        // Copy executable to bin folder
-        Path executableFile = binDir.resolve(getLauncherName(params));
-
-        try (InputStream is_launcher =
-                getResourceAsStream(getLauncherResourceName(params))) {
-            writeEntry(is_launcher, executableFile);
-        }
-
-        File launcher = executableFile.toFile();
-        launcher.setWritable(true, true);
-
-        // Update branding of EXE file
-        if (REBRAND_EXECUTABLE.fetchFrom(params)) {
-            try {
-                String tempDirectory = WindowsDefender.getUserTempDirectory();
-                if (Arguments.CLIOptions.context().userProvidedBuildRoot) {
-                    tempDirectory =
-                            TEMP_ROOT.fetchFrom(params).getAbsolutePath();
-                }
-                if (WindowsDefender.isThereAPotentialWindowsDefenderIssue(
-                        tempDirectory)) {
-                    Log.verbose(MessageFormat.format(I18N.getString(
-                            "message.potential.windows.defender.issue"),
-                            tempDirectory));
-                }
-
-                launcher.setWritable(true);
-
-                if (iconTarget.exists()) {
-                    iconSwap(iconTarget.getAbsolutePath(),
-                            launcher.getAbsolutePath());
-                }
-
-                File executableProperties =
-                        getConfig_ExecutableProperties(params);
-
-                if (executableProperties.exists()) {
-                    if (versionSwap(executableProperties.getAbsolutePath(),
-                            launcher.getAbsolutePath()) != 0) {
-                        throw new RuntimeException(MessageFormat.format(
-                                I18N.getString("error.version-swap"),
-                                executableProperties.getAbsolutePath()));
-                    }
-                }
-            } finally {
-                executableFile.toFile().setExecutable(true);
-                executableFile.toFile().setReadOnly();
-            }
-        }
-
-        Files.copy(iconTarget.toPath(),
-                binDir.resolve(APP_NAME.fetchFrom(params) + ".ico"));
-    }
-
-    private void copyApplication(Map<String, ? super Object> params)
-            throws IOException {
-        List<RelativeFileSet> appResourcesList =
-                APP_RESOURCES_LIST.fetchFrom(params);
-        if (appResourcesList == null) {
-            throw new RuntimeException("Null app resources?");
-        }
-        for (RelativeFileSet appResources : appResourcesList) {
-            if (appResources == null) {
-                throw new RuntimeException("Null app resources?");
-            }
-            File srcdir = appResources.getBaseDirectory();
-            for (String fname : appResources.getIncludedFiles()) {
-                copyEntry(appDir, srcdir, fname);
-            }
-        }
-    }
-
-    private static native int iconSwap(String iconTarget, String launcher);
-
-    private static native int versionSwap(String executableProperties,
-            String launcher);
-
-}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsBundlerParam.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.text.MessageFormat;
-import java.util.Map;
-import java.util.ResourceBundle;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-
-class WindowsBundlerParam<T> extends StandardBundlerParam<T> {
-
-    private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.WinResources");
-
-    WindowsBundlerParam(String id, Class<T> valueType,
-            Function<Map<String, ? super Object>, T> defaultValueFunction,
-            BiFunction<String,
-            Map<String, ? super Object>, T> stringConverter) {
-        super(id, valueType, defaultValueFunction, stringConverter);
-    }
-
-    static final BundlerParamInfo<String> INSTALLER_FILE_NAME =
-            new StandardBundlerParam<> (
-            "win.installerName",
-            String.class,
-            params -> {
-                String nm = APP_NAME.fetchFrom(params);
-                if (nm == null) return null;
-
-                String version = VERSION.fetchFrom(params);
-                if (version == null) {
-                    return nm;
-                } else {
-                    return nm + "-" + version;
-                }
-            },
-            (s, p) -> s);
-
-    static final StandardBundlerParam<String> MENU_GROUP =
-            new StandardBundlerParam<>(
-                    Arguments.CLIOptions.WIN_MENU_GROUP.getId(),
-                    String.class,
-                    params -> I18N.getString("param.menu-group.default"),
-                    (s, p) -> s
-            );
-
-    static final BundlerParamInfo<Boolean> INSTALLDIR_CHOOSER =
-            new StandardBundlerParam<> (
-            Arguments.CLIOptions.WIN_DIR_CHOOSER.getId(),
-            Boolean.class,
-            params -> Boolean.FALSE,
-            (s, p) -> Boolean.valueOf(s)
-    );
-
-    static final BundlerParamInfo<String> WINDOWS_INSTALL_DIR =
-            new StandardBundlerParam<>(
-            "windows-install-dir",
-            String.class,
-            params -> {
-                 String dir = INSTALL_DIR.fetchFrom(params);
-                 if (dir != null) {
-                     if (dir.contains(":") || dir.contains("..")) {
-                         Log.error(MessageFormat.format(I18N.getString(
-                                "message.invalid.install.dir"), dir,
-                                APP_NAME.fetchFrom(params)));
-                     } else {
-                        if (dir.startsWith("\\")) {
-                             dir = dir.substring(1);
-                        }
-                        if (dir.endsWith("\\")) {
-                             dir = dir.substring(0, dir.length() - 1);
-                        }
-                        return dir;
-                     }
-                 }
-                 return APP_NAME.fetchFrom(params); // Default to app name
-             },
-            (s, p) -> s
-    );
-}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsDefender.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.List;
-
-final class WindowsDefender {
-
-    private WindowsDefender() {}
-
-    static final boolean isThereAPotentialWindowsDefenderIssue(String dir) {
-        boolean result = false;
-
-        if (Platform.getPlatform() == Platform.WINDOWS &&
-            Platform.getMajorVersion() == 10) {
-
-            // If DisableRealtimeMonitoring is not enabled then there
-            // may be a problem.
-            if (!WindowsRegistry.readDisableRealtimeMonitoring() &&
-                !isDirectoryInExclusionPath(dir)) {
-                result = true;
-            }
-        }
-
-        return result;
-    }
-
-    private static boolean isDirectoryInExclusionPath(String dir) {
-        boolean result = false;
-        // If the user temp directory is not found in the exclusion
-        // list then there may be a problem.
-        List<String> paths = WindowsRegistry.readExclusionsPaths();
-        for (String s : paths) {
-            if (WindowsRegistry.comparePaths(s, dir)) {
-                result = true;
-                break;
-            }
-        }
-
-        return result;
-    }
-
-    static final String getUserTempDirectory() {
-        String tempDirectory = System.getProperty("java.io.tmpdir");
-        return tempDirectory;
-    }
-}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WindowsRegistry.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.List;
-
-final class WindowsRegistry {
-
-    // Currently we only support HKEY_LOCAL_MACHINE. Native implementation will
-    // require support for additinal HKEY if needed.
-    private static final int HKEY_LOCAL_MACHINE = 1;
-
-    static {
-        System.loadLibrary("jpackage");
-    }
-
-    private WindowsRegistry() {}
-
-    /**
-     * Reads the registry value for DisableRealtimeMonitoring.
-     * @return true if DisableRealtimeMonitoring is set to 0x1,
-     *         false otherwise.
-     */
-    static final boolean readDisableRealtimeMonitoring() {
-        final String subKey = "Software\\Microsoft\\"
-                  + "Windows Defender\\Real-Time Protection";
-        final String value = "DisableRealtimeMonitoring";
-        int result = readDwordValue(HKEY_LOCAL_MACHINE, subKey, value, 0);
-        return (result == 1);
-    }
-
-    static final List<String> readExclusionsPaths() {
-        List<String> result = new ArrayList<>();
-        final String subKey = "Software\\Microsoft\\"
-                + "Windows Defender\\Exclusions\\Paths";
-        long lKey = openRegistryKey(HKEY_LOCAL_MACHINE, subKey);
-        if (lKey == 0) {
-            return result;
-        }
-
-        String valueName;
-        int index = 0;
-        do {
-            valueName = enumRegistryValue(lKey, index);
-            if (valueName != null) {
-                result.add(valueName);
-                index++;
-            }
-        } while (valueName != null);
-
-        closeRegistryKey(lKey);
-
-        return result;
-    }
-
-    /**
-     * Reads DWORD registry value.
-     *
-     * @param key one of HKEY predefine value
-     * @param subKey registry sub key
-     * @param value value to read
-     * @param defaultValue default value in case if subKey or value not found
-     *                     or any other errors occurred
-     * @return value's data only if it was read successfully, otherwise
-     *         defaultValue
-     */
-    private static native int readDwordValue(int key, String subKey,
-            String value, int defaultValue);
-
-    /**
-     * Open registry key.
-     *
-     * @param key one of HKEY predefine value
-     * @param subKey registry sub key
-     * @return native handle to open key
-     */
-    private static native long openRegistryKey(int key, String subKey);
-
-    /**
-     * Enumerates the values for registry key.
-     *
-     * @param lKey native handle to open key returned by openRegistryKey
-     * @param index index of value starting from 0. Increment until this
-     *              function returns NULL which means no more values.
-     * @return returns value or NULL if error or no more data
-     */
-    private static native String enumRegistryValue(long lKey, int index);
-
-    /**
-     * Close registry key.
-     *
-     * @param lKey native handle to open key returned by openRegistryKey
-     */
-    private static native void closeRegistryKey(long lKey);
-
-    /**
-     * Compares two Windows paths regardless case and if paths
-     * are short or long.
-     *
-     * @param path1 path to compare
-     * @param path2 path to compare
-     * @return true if paths point to same location
-     */
-    public static native boolean comparePaths(String path1, String path2);
-}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * Copyright (c) 2019, 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.Files;
-import java.nio.file.Path;
-import java.util.*;
-import java.util.function.UnaryOperator;
-import java.util.stream.Stream;
-
-/**
- * WiX pipeline. Compiles and links WiX sources.
- */
-public class WixPipeline {
-    WixPipeline() {
-        sources = new ArrayList<>();
-        lightOptions = new ArrayList<>();
-    }
-
-    WixPipeline setToolset(Map<WixTool, Path> v) {
-        toolset = v;
-        return this;
-    }
-
-    WixPipeline setWixVariables(Map<String, String> v) {
-        wixVariables = v;
-        return this;
-    }
-
-    WixPipeline setWixObjDir(Path v) {
-        wixObjDir = v;
-        return this;
-    }
-
-    WixPipeline setWorkDir(Path v) {
-        workDir = v;
-        return this;
-    }
-
-    WixPipeline addSource(Path source, Map<String, String> wixVariables) {
-        WixSource entry = new WixSource();
-        entry.source = source;
-        entry.variables = wixVariables;
-        sources.add(entry);
-        return this;
-    }
-
-    WixPipeline addLightOptions(String ... v) {
-        lightOptions.addAll(List.of(v));
-        return this;
-    }
-
-    void buildMsi(Path msi) throws IOException {
-        List<Path> wixObjs = new ArrayList<>();
-        for (var source : sources) {
-            wixObjs.add(compile(source));
-        }
-
-        List<String> lightCmdline = new ArrayList<>(List.of(
-                toolset.get(WixTool.Light).toString(),
-                "-nologo",
-                "-spdb",
-                "-ext", "WixUtilExtension",
-                "-out", msi.toString()
-        ));
-
-        lightCmdline.addAll(lightOptions);
-        wixObjs.stream().map(Path::toString).forEach(lightCmdline::add);
-
-        Files.createDirectories(msi.getParent());
-        execute(lightCmdline);
-    }
-
-    private Path compile(WixSource wixSource) throws IOException {
-        UnaryOperator<Path> adjustPath = path -> {
-            return workDir != null ? path.toAbsolutePath() : path;
-        };
-
-        Path wixObj = adjustPath.apply(wixObjDir).resolve(IOUtils.replaceSuffix(
-                wixSource.source.getFileName(), ".wixobj"));
-
-        List<String> cmdline = new ArrayList<>(List.of(
-                toolset.get(WixTool.Candle).toString(),
-                "-nologo",
-                adjustPath.apply(wixSource.source).toString(),
-                "-ext", "WixUtilExtension",
-                "-arch", "x64",
-                "-out", wixObj.toAbsolutePath().toString()
-        ));
-
-        Map<String, String> appliedVaribales = new HashMap<>();
-        Stream.of(wixVariables, wixSource.variables)
-                .filter(Objects::nonNull)
-                .forEachOrdered(appliedVaribales::putAll);
-
-        appliedVaribales.entrySet().stream().map(wixVar -> String.format("-d%s=%s",
-                wixVar.getKey(), wixVar.getValue())).forEachOrdered(
-                cmdline::add);
-
-        execute(cmdline);
-
-        return wixObj;
-    }
-
-    private void execute(List<String> cmdline) throws IOException {
-        Executor.of(new ProcessBuilder(cmdline).directory(
-                workDir != null ? workDir.toFile() : null)).executeExpectSuccess();
-    }
-
-    private final static class WixSource {
-        Path source;
-        Map<String, String> variables;
-    }
-
-    private Map<WixTool, Path> toolset;
-    private Map<String, String> wixVariables;
-    private List<String> lightOptions;
-    private Path wixObjDir;
-    private Path workDir;
-    private List<WixSource> sources;
-}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourcesBuilder.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,847 +0,0 @@
-/*
- * Copyright (c) 2019, 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.charset.StandardCharsets;
-import java.nio.file.Path;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.function.*;
-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.StandardBundlerParam.*;
-import static jdk.jpackage.internal.WinMsiBundler.*;
-import static jdk.jpackage.internal.WindowsBundlerParam.MENU_GROUP;
-import static jdk.jpackage.internal.WindowsBundlerParam.WINDOWS_INSTALL_DIR;
-
-/**
- * Creates application WiX source files.
- */
-class WixSourcesBuilder {
-
-    WixSourcesBuilder setWixVersion(DottedVersion v) {
-        wixVersion = v;
-        return this;
-    }
-
-    WixSourcesBuilder initFromParams(Path appImageRoot,
-            Map<String, ? super Object> params) {
-        Supplier<ApplicationLayout> appImageSupplier = () -> {
-            if (StandardBundlerParam.isRuntimeInstaller(params)) {
-                return ApplicationLayout.javaRuntime();
-            } else {
-                return ApplicationLayout.platformAppImage();
-            }
-        };
-
-        systemWide = MSI_SYSTEM_WIDE.fetchFrom(params);
-
-        registryKeyPath = Path.of("Software",
-                VENDOR.fetchFrom(params),
-                APP_NAME.fetchFrom(params),
-                VERSION.fetchFrom(params)).toString();
-
-        installDir = (systemWide ? PROGRAM_FILES : LOCAL_PROGRAM_FILES).resolve(
-                WINDOWS_INSTALL_DIR.fetchFrom(params));
-
-        do {
-            ApplicationLayout layout = appImageSupplier.get();
-            // Don't want AppImageFile.FILENAME in installed application.
-            // Register it with app image at a role without a match in installed
-            // app layout to exclude it from layout transformation.
-            layout.pathGroup().setPath(new Object(),
-                    AppImageFile.getPathInAppImage(Path.of("")));
-
-            // Want absolute paths to source files in generated WiX sources.
-            // This is to handle scenario if sources would be processed from
-            // differnt current directory.
-            appImage = layout.resolveAt(appImageRoot.toAbsolutePath().normalize());
-        } while (false);
-
-        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);
-        }
-
-        if (StandardBundlerParam.isRuntimeInstaller(params)) {
-            launcherPaths = Collections.emptyList();
-        } else {
-            launcherPaths = AppImageFile.getLauncherNames(appImageRoot, params).stream()
-                    .map(name -> installedAppImage.launchersDirectory().resolve(name))
-                    .map(WixSourcesBuilder::addExeSuffixToPath)
-                    .collect(Collectors.toList());
-        }
-
-        programMenuFolderName = MENU_GROUP.fetchFrom(params);
-
-        initFileAssociations(params);
-
-        return this;
-    }
-
-    void createMainFragment(Path file) 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>
-        });
-    }
-
-    void logWixFeatures() {
-        if (wixVersion.compareTo("3.6") >= 0) {
-            Log.verbose(MessageFormat.format(I18N.getString(
-                    "message.use-wix36-features"), wixVersion));
-        }
-    }
-
-    private void normalizeFileAssociation(FileAssociation fa) {
-        fa.launcherPath = addExeSuffixToPath(
-                installedAppImage.launchersDirectory().resolve(fa.launcherPath));
-
-        if (fa.iconPath != null && !fa.iconPath.toFile().exists()) {
-            fa.iconPath = null;
-        }
-
-        if (fa.iconPath != null) {
-            fa.iconPath = fa.iconPath.toAbsolutePath();
-        }
-
-        // Filter out empty extensions.
-        fa.extensions = fa.extensions.stream().filter(Predicate.not(
-                String::isEmpty)).collect(Collectors.toList());
-    }
-
-    private static Path addExeSuffixToPath(Path path) {
-        return IOUtils.addSuffix(path, ".exe");
-    }
-
-    private Path getInstalledFaIcoPath(FileAssociation fa) {
-        String fname = String.format("fa_%s.ico", String.join("_", fa.extensions));
-        return installedAppImage.destktopIntegrationDirectory().resolve(fname);
-    }
-
-    private void initFileAssociations(Map<String, ? super Object> params) {
-        associations = FileAssociation.fetchFrom(params).stream()
-                .peek(this::normalizeFileAssociation)
-                // Filter out file associations without extensions.
-                .filter(fa -> !fa.extensions.isEmpty())
-                .collect(Collectors.toList());
-
-        associations.stream().filter(fa -> fa.iconPath != null).forEach(fa -> {
-            // Need to add fa icon in the image.
-            Object key = new Object();
-            appImage.pathGroup().setPath(key, fa.iconPath);
-            installedAppImage.pathGroup().setPath(key, getInstalledFaIcoPath(fa));
-        });
-    }
-
-    private static UUID createNameUUID(String str) {
-        return UUID.nameUUIDFromBytes(str.getBytes(StandardCharsets.UTF_8));
-    }
-
-    private static UUID createNameUUID(Path path, String role) {
-        if (path.isAbsolute() || !ROOT_DIRS.contains(path.getName(0))) {
-            throw throwInvalidPathException(path);
-        }
-        // Paths are case insensitive on Windows
-        String keyPath = path.toString().toLowerCase();
-        if (role != null) {
-            keyPath = role + "@" + keyPath;
-        }
-        return createNameUUID(keyPath);
-    }
-
-    /**
-     * Value for Id attribute of various WiX elements.
-     */
-    enum Id {
-        File,
-        Folder("dir"),
-        Shortcut,
-        ProgId,
-        Icon,
-        CreateFolder("mkdir"),
-        RemoveFolder("rm");
-
-        Id() {
-            this.prefix = name().toLowerCase();
-        }
-
-        Id(String prefix) {
-            this.prefix = prefix;
-        }
-
-        String of(Path path) {
-            if (this == Folder && KNOWN_DIRS.contains(path)) {
-                return path.getFileName().toString();
-            }
-
-            String result = of(path, prefix, name());
-
-            if (this == Icon) {
-                // Icon id constructed from UUID value is too long and triggers
-                // CNDL1000 warning, so use Java hash code instead.
-                result = String.format("%s%d", prefix, result.hashCode()).replace(
-                        "-", "_");
-            }
-
-            return result;
-        }
-
-        private static String of(Path path, String prefix, String role) {
-            Objects.requireNonNull(role);
-            Objects.requireNonNull(prefix);
-            return String.format("%s%s", prefix,
-                    createNameUUID(path, role).toString().replace("-", ""));
-        }
-
-        static String of(Path path, String prefix) {
-            return of(path, prefix, prefix);
-        }
-
-        private final String prefix;
-    }
-
-    enum Component {
-        File(cfg().file()),
-        Shortcut(cfg().file().withRegistryKeyPath()),
-        ProgId(cfg().file().withRegistryKeyPath()),
-        CreateFolder(cfg().withRegistryKeyPath()),
-        RemoveFolder(cfg().withRegistryKeyPath());
-
-        Component() {
-            this.cfg = cfg();
-            this.id = Id.valueOf(name());
-        }
-
-        Component(Config cfg) {
-            this.cfg = cfg;
-            this.id = Id.valueOf(name());
-        }
-
-        UUID guidOf(Path path) {
-            return createNameUUID(path, name());
-        }
-
-        String idOf(Path path) {
-            return id.of(path);
-        }
-
-        boolean isRegistryKeyPath() {
-            return cfg.withRegistryKeyPath;
-        }
-
-        boolean isFile() {
-            return cfg.isFile;
-        }
-
-        static void startElement(XMLStreamWriter xml, String componentId,
-                String componentGuid) throws XMLStreamException, IOException {
-            xml.writeStartElement("Component");
-            xml.writeAttribute("Win64", "yes");
-            xml.writeAttribute("Id", componentId);
-            xml.writeAttribute("Guid", componentGuid);
-        }
-
-        private static final class Config {
-            Config withRegistryKeyPath() {
-                withRegistryKeyPath = true;
-                return this;
-            }
-
-            Config file() {
-                isFile = true;
-                return this;
-            }
-
-            private boolean isFile;
-            private boolean withRegistryKeyPath;
-        }
-
-        private static Config cfg() {
-            return new Config();
-        }
-
-        private final Config cfg;
-        private final Id id;
-    };
-
-    private static void addComponentGroup(XMLStreamWriter xml, String id,
-            List<String> componentIds) throws XMLStreamException, IOException {
-        xml.writeStartElement("ComponentGroup");
-        xml.writeAttribute("Id", id);
-        componentIds = componentIds.stream().filter(Objects::nonNull).collect(
-                Collectors.toList());
-        for (var componentId : componentIds) {
-            xml.writeStartElement("ComponentRef");
-            xml.writeAttribute("Id", componentId);
-            xml.writeEndElement();
-        }
-        xml.writeEndElement();
-    }
-
-    private String addComponent(XMLStreamWriter xml, Path path,
-            Component role, XmlConsumer xmlConsumer) throws XMLStreamException,
-            IOException {
-
-        final Path directoryRefPath;
-        if (role.isFile()) {
-            directoryRefPath = path.getParent();
-        } else {
-            directoryRefPath = path;
-        }
-
-        xml.writeStartElement("DirectoryRef");
-        xml.writeAttribute("Id", Id.Folder.of(directoryRefPath));
-
-        final String componentId = "c" + role.idOf(path);
-        Component.startElement(xml, componentId, String.format("{%s}",
-                role.guidOf(path)));
-
-        boolean isRegistryKeyPath = !systemWide || role.isRegistryKeyPath();
-        if (isRegistryKeyPath) {
-            addRegistryKeyPath(xml, directoryRefPath);
-            if ((role.isFile() || (role == Component.CreateFolder
-                    && !systemWide)) && !SYSTEM_DIRS.contains(directoryRefPath)) {
-                xml.writeStartElement("RemoveFolder");
-                int counter = Optional.ofNullable(removeFolderItems.get(
-                        directoryRefPath)).orElse(Integer.valueOf(0)).intValue() + 1;
-                removeFolderItems.put(directoryRefPath, counter);
-                xml.writeAttribute("Id", String.format("%s_%d", Id.RemoveFolder.of(
-                        directoryRefPath), counter));
-                xml.writeAttribute("On", "uninstall");
-                xml.writeEndElement();
-            }
-        }
-
-        xml.writeStartElement(role.name());
-        if (role != Component.CreateFolder) {
-            xml.writeAttribute("Id", role.idOf(path));
-        }
-
-        if (!isRegistryKeyPath) {
-            xml.writeAttribute("KeyPath", "yes");
-        }
-
-        xmlConsumer.accept(xml);
-        xml.writeEndElement();
-
-        xml.writeEndElement(); // <Component>
-        xml.writeEndElement(); // <DirectoryRef>
-
-        return componentId;
-    }
-
-    private void addFaComponentGroup(XMLStreamWriter xml)
-            throws XMLStreamException, IOException {
-
-        List<String> componentIds = new ArrayList<>();
-        for (var fa : associations) {
-            componentIds.addAll(addFaComponents(xml, fa));
-        }
-        addComponentGroup(xml, "FileAssociations", componentIds);
-    }
-
-    private void addShortcutComponentGroup(XMLStreamWriter xml) throws
-            XMLStreamException, IOException {
-        List<String> componentIds = new ArrayList<>();
-        Set<ShortcutsFolder> defineShortcutFolders = new HashSet<>();
-        for (var launcherPath : launcherPaths) {
-            for (var folder : shortcutFolders) {
-                String componentId = addShortcutComponent(xml, launcherPath,
-                        folder);
-                if (componentId != null) {
-                    defineShortcutFolders.add(folder);
-                    componentIds.add(componentId);
-                }
-            }
-        }
-
-        for (var folder : defineShortcutFolders) {
-            Path path = folder.getPath(this);
-            componentIds.addAll(addRootBranch(xml, path));
-        }
-
-        addComponentGroup(xml, "Shortcuts", componentIds);
-    }
-
-    private String addShortcutComponent(XMLStreamWriter xml, Path launcherPath,
-            ShortcutsFolder folder) throws XMLStreamException, IOException {
-        Objects.requireNonNull(folder);
-
-        if (!INSTALLDIR.equals(launcherPath.getName(0))) {
-            throw throwInvalidPathException(launcherPath);
-        }
-
-        String launcherBasename = IOUtils.replaceSuffix(
-                launcherPath.getFileName(), "").toString();
-
-        Path shortcutPath = folder.getPath(this).resolve(launcherBasename);
-        return addComponent(xml, shortcutPath, Component.Shortcut, unused -> {
-            final Path icoFile = IOUtils.addSuffix(
-                    installedAppImage.destktopIntegrationDirectory().resolve(
-                            launcherBasename), ".ico");
-
-            xml.writeAttribute("Name", launcherBasename);
-            xml.writeAttribute("WorkingDirectory", INSTALLDIR.toString());
-            xml.writeAttribute("Advertise", "no");
-            xml.writeAttribute("IconIndex", "0");
-            xml.writeAttribute("Target", String.format("[#%s]",
-                    Component.File.idOf(launcherPath)));
-            xml.writeAttribute("Icon", Id.Icon.of(icoFile));
-        });
-    }
-
-    private List<String> addFaComponents(XMLStreamWriter xml,
-            FileAssociation fa) throws XMLStreamException, IOException {
-        List<String> components = new ArrayList<>();
-        for (var extension: fa.extensions) {
-            Path path = INSTALLDIR.resolve(String.format("%s_%s", extension,
-                    fa.launcherPath.getFileName()));
-            components.add(addComponent(xml, path, Component.ProgId, unused -> {
-                xml.writeAttribute("Description", fa.description);
-
-                if (fa.iconPath != null) {
-                    xml.writeAttribute("Icon", Id.File.of(getInstalledFaIcoPath(
-                            fa)));
-                    xml.writeAttribute("IconIndex", "0");
-                }
-
-                xml.writeStartElement("Extension");
-                xml.writeAttribute("Id", extension);
-                xml.writeAttribute("Advertise", "no");
-
-                var mimeIt = fa.mimeTypes.iterator();
-                if (mimeIt.hasNext()) {
-                    String mime = mimeIt.next();
-                    xml.writeAttribute("ContentType", mime);
-
-                    if (!defaultedMimes.contains(mime)) {
-                        xml.writeStartElement("MIME");
-                        xml.writeAttribute("ContentType", mime);
-                        xml.writeAttribute("Default", "yes");
-                        xml.writeEndElement();
-                        defaultedMimes.add(mime);
-                    }
-                }
-
-                xml.writeStartElement("Verb");
-                xml.writeAttribute("Id", "open");
-                xml.writeAttribute("Command", "Open");
-                xml.writeAttribute("Argument", "%1");
-                xml.writeAttribute("TargetFile", Id.File.of(fa.launcherPath));
-                xml.writeEndElement(); // <Verb>
-
-                xml.writeEndElement(); // <Extension>
-            }));
-        }
-
-        return components;
-    }
-
-    private List<String> addRootBranch(XMLStreamWriter xml, Path path)
-            throws XMLStreamException, IOException {
-        if (!ROOT_DIRS.contains(path.getName(0))) {
-            throw throwInvalidPathException(path);
-        }
-
-        Function<Path, String> createDirectoryName = dir -> null;
-
-        boolean sysDir = true;
-        int levels = 1;
-        var dirIt = path.iterator();
-        xml.writeStartElement("DirectoryRef");
-        xml.writeAttribute("Id", dirIt.next().toString());
-
-        path = path.getName(0);
-        while (dirIt.hasNext()) {
-            levels++;
-            Path name = dirIt.next();
-            path = path.resolve(name);
-
-            if (sysDir && !SYSTEM_DIRS.contains(path)) {
-                sysDir = false;
-                createDirectoryName = dir -> dir.getFileName().toString();
-            }
-
-            final String directoryId;
-            if (!sysDir && path.equals(installDir)) {
-                directoryId = INSTALLDIR.toString();
-            } else {
-                directoryId = Id.Folder.of(path);
-            }
-            xml.writeStartElement("Directory");
-            xml.writeAttribute("Id", directoryId);
-
-            String directoryName = createDirectoryName.apply(path);
-            if (directoryName != null) {
-                xml.writeAttribute("Name", directoryName);
-            }
-        }
-
-        while (0 != levels--) {
-            xml.writeEndElement();
-        }
-
-        List<String> componentIds = new ArrayList<>();
-        while (!SYSTEM_DIRS.contains(path = path.getParent())) {
-            componentIds.add(addRemoveDirectoryComponent(xml, path));
-        }
-
-        return componentIds;
-    }
-
-    private String addRemoveDirectoryComponent(XMLStreamWriter xml, Path path)
-            throws XMLStreamException, IOException {
-        return addComponent(xml, path, Component.RemoveFolder,
-                unused -> xml.writeAttribute("On", "uninstall"));
-    }
-
-    private List<String> addDirectoryHierarchy(XMLStreamWriter xml)
-            throws XMLStreamException, IOException {
-
-        Set<Path> allDirs = new HashSet<>();
-        Set<Path> emptyDirs = new HashSet<>();
-        appImage.transform(installedAppImage, new PathGroup.TransformHandler() {
-            @Override
-            public void copyFile(Path src, Path dst) throws IOException {
-                Path dir = dst.getParent();
-                createDirectory(dir);
-                emptyDirs.remove(dir);
-            }
-
-            @Override
-            public void createDirectory(final Path dir) throws IOException {
-                if (!allDirs.contains(dir)) {
-                    emptyDirs.add(dir);
-                }
-
-                Path it = dir;
-                while (it != null && allDirs.add(it)) {
-                    it = it.getParent();
-                }
-
-                it = dir;
-                while ((it = it.getParent()) != null && emptyDirs.remove(it));
-            }
-        });
-
-        List<String> componentIds = new ArrayList<>();
-        for (var dir : emptyDirs) {
-            componentIds.add(addComponent(xml, dir, Component.CreateFolder,
-                    unused -> {}));
-        }
-
-        if (!systemWide) {
-            // Per-user install requires <RemoveFolder> component in every
-            // directory.
-            for (var dir : allDirs.stream()
-                    .filter(Predicate.not(emptyDirs::contains))
-                    .filter(Predicate.not(removeFolderItems::containsKey))
-                    .collect(Collectors.toList())) {
-                componentIds.add(addRemoveDirectoryComponent(xml, dir));
-            }
-        }
-
-        allDirs.remove(INSTALLDIR);
-        for (var dir : allDirs) {
-            xml.writeStartElement("DirectoryRef");
-            xml.writeAttribute("Id", Id.Folder.of(dir.getParent()));
-            xml.writeStartElement("Directory");
-            xml.writeAttribute("Id", Id.Folder.of(dir));
-            xml.writeAttribute("Name", dir.getFileName().toString());
-            xml.writeEndElement();
-            xml.writeEndElement();
-        }
-
-        componentIds.addAll(addRootBranch(xml, installDir));
-
-        return componentIds;
-    }
-
-    private void addFilesComponentGroup(XMLStreamWriter xml)
-            throws XMLStreamException, IOException {
-
-        List<Map.Entry<Path, Path>> files = new ArrayList<>();
-        appImage.transform(installedAppImage, new PathGroup.TransformHandler() {
-            @Override
-            public void copyFile(Path src, Path dst) throws IOException {
-                files.add(Map.entry(src, dst));
-            }
-
-            @Override
-            public void createDirectory(final Path dir) throws IOException {
-            }
-        });
-
-        List<String> componentIds = new ArrayList<>();
-        for (var file : files) {
-            Path src = file.getKey();
-            Path dst = file.getValue();
-
-            componentIds.add(addComponent(xml, dst, Component.File, unused -> {
-                xml.writeAttribute("Source", src.normalize().toString());
-                Path name = dst.getFileName();
-                if (!name.equals(src.getFileName())) {
-                    xml.writeAttribute("Name", name.toString());
-                }
-            }));
-        }
-
-        componentIds.addAll(addDirectoryHierarchy(xml));
-
-        componentIds.add(addDirectoryCleaner(xml, INSTALLDIR));
-
-        addComponentGroup(xml, "Files", componentIds);
-    }
-
-    private void addIconsFragment(XMLStreamWriter xml) throws
-            XMLStreamException, IOException {
-
-        PathGroup srcPathGroup = appImage.pathGroup();
-        PathGroup dstPathGroup = installedAppImage.pathGroup();
-
-        // Build list of copy operations for all .ico files in application image
-        List<Map.Entry<Path, Path>> icoFiles = new ArrayList<>();
-        srcPathGroup.transform(dstPathGroup, new PathGroup.TransformHandler() {
-            @Override
-            public void copyFile(Path src, Path dst) throws IOException {
-                if (src.getFileName().toString().endsWith(".ico")) {
-                    icoFiles.add(Map.entry(src, dst));
-                }
-            }
-
-            @Override
-            public void createDirectory(Path dst) throws IOException {
-            }
-        });
-
-        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
-            XMLStreamException, IOException {
-        addRegistryKeyPath(xml, path, () -> "ProductCode", () -> "[ProductCode]");
-    }
-
-    private void addRegistryKeyPath(XMLStreamWriter xml, Path path,
-            Supplier<String> nameAttr, Supplier<String> valueAttr) throws
-            XMLStreamException, IOException {
-
-        String regRoot = USER_PROFILE_DIRS.stream().anyMatch(path::startsWith)
-                || !systemWide ? "HKCU" : "HKLM";
-
-        xml.writeStartElement("RegistryKey");
-        xml.writeAttribute("Root", regRoot);
-        xml.writeAttribute("Key", registryKeyPath);
-        if (wixVersion.compareTo("3.6") < 0) {
-            xml.writeAttribute("Action", "createAndRemoveOnUninstall");
-        }
-        xml.writeStartElement("RegistryValue");
-        xml.writeAttribute("Type", "string");
-        xml.writeAttribute("KeyPath", "yes");
-        xml.writeAttribute("Name", nameAttr.get());
-        xml.writeAttribute("Value", valueAttr.get());
-        xml.writeEndElement(); // <RegistryValue>
-        xml.writeEndElement(); // <RegistryKey>
-    }
-
-    private String addDirectoryCleaner(XMLStreamWriter xml, Path path) throws
-            XMLStreamException, IOException {
-        if (wixVersion.compareTo("3.6") < 0) {
-            return null;
-        }
-
-        // rm -rf
-        final String baseId = Id.of(path, "rm_rf");
-        final String propertyId = baseId.toUpperCase();
-        final String componentId = ("c" + baseId);
-
-        xml.writeStartElement("Property");
-        xml.writeAttribute("Id", propertyId);
-        xml.writeStartElement("RegistrySearch");
-        xml.writeAttribute("Id", Id.of(path, "regsearch"));
-        xml.writeAttribute("Root", systemWide ? "HKLM" : "HKCU");
-        xml.writeAttribute("Key", registryKeyPath);
-        xml.writeAttribute("Type", "raw");
-        xml.writeAttribute("Name", propertyId);
-        xml.writeEndElement(); // <RegistrySearch>
-        xml.writeEndElement(); // <Property>
-
-        xml.writeStartElement("DirectoryRef");
-        xml.writeAttribute("Id", INSTALLDIR.toString());
-        Component.startElement(xml, componentId, "*");
-
-        addRegistryKeyPath(xml, INSTALLDIR, () -> propertyId, () -> {
-            // The following code converts a path to value to be saved in registry.
-            // E.g.:
-            //  INSTALLDIR -> [INSTALLDIR]
-            //  TERGETDIR/ProgramFiles64Folder/foo/bar -> [ProgramFiles64Folder]foo/bar
-            final Path rootDir = KNOWN_DIRS.stream()
-                    .sorted(Comparator.comparing(Path::getNameCount).reversed())
-                    .filter(path::startsWith)
-                    .findFirst().get();
-            StringBuilder sb = new StringBuilder();
-            sb.append(String.format("[%s]", rootDir.getFileName().toString()));
-            sb.append(rootDir.relativize(path).toString());
-            return sb.toString();
-        });
-
-        xml.writeStartElement(
-                "http://schemas.microsoft.com/wix/UtilExtension",
-                "RemoveFolderEx");
-        xml.writeAttribute("On", "uninstall");
-        xml.writeAttribute("Property", propertyId);
-        xml.writeEndElement(); // <RemoveFolderEx>
-        xml.writeEndElement(); // <Component>
-        xml.writeEndElement(); // <DirectoryRef>
-
-        return componentId;
-    }
-
-    private static IllegalArgumentException throwInvalidPathException(Path v) {
-        throw new IllegalArgumentException(String.format("Invalid path [%s]", v));
-    }
-
-    enum ShortcutsFolder {
-        ProgramMenu(PROGRAM_MENU_PATH),
-        Desktop(DESKTOP_PATH);
-
-        private ShortcutsFolder(Path root) {
-            this.root = root;
-        }
-
-        Path getPath(WixSourcesBuilder outer) {
-            if (this == ProgramMenu) {
-                return root.resolve(outer.programMenuFolderName);
-            }
-            return root;
-        }
-
-        private final Path root;
-    }
-
-    private DottedVersion wixVersion;
-
-    private boolean systemWide;
-
-    private String registryKeyPath;
-
-    private Path installDir;
-
-    private String programMenuFolderName;
-
-    private List<FileAssociation> associations;
-
-    private Set<ShortcutsFolder> shortcutFolders;
-
-    private List<Path> launcherPaths;
-
-    private ApplicationLayout appImage;
-    private ApplicationLayout installedAppImage;
-
-    private Map<Path, Integer> removeFolderItems;
-    private Set<String> defaultedMimes;
-
-    private final static Path TARGETDIR = Path.of("TARGETDIR");
-
-    private final static Path INSTALLDIR = Path.of("INSTALLDIR");
-
-    private final static Set<Path> ROOT_DIRS = Set.of(INSTALLDIR, TARGETDIR);
-
-    private final static Path PROGRAM_MENU_PATH = TARGETDIR.resolve("ProgramMenuFolder");
-
-    private final static Path DESKTOP_PATH = TARGETDIR.resolve("DesktopFolder");
-
-    private final static Path PROGRAM_FILES = TARGETDIR.resolve("ProgramFiles64Folder");
-
-    private final static Path LOCAL_PROGRAM_FILES = TARGETDIR.resolve("LocalAppDataFolder");
-
-    private final static Set<Path> SYSTEM_DIRS = Set.of(TARGETDIR,
-            PROGRAM_MENU_PATH, DESKTOP_PATH, PROGRAM_FILES, LOCAL_PROGRAM_FILES);
-
-    private final static Set<Path> KNOWN_DIRS = Stream.of(Set.of(INSTALLDIR),
-            SYSTEM_DIRS).flatMap(Set::stream).collect(
-            Collectors.toUnmodifiableSet());
-
-    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 WindowsBundlerParam<>(
-                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 WindowsBundlerParam<>(
-                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)
-        );
-}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixTool.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2019, 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.*;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * WiX tool.
- */
-public enum WixTool {
-    Candle, Light;
-
-    static final class ToolInfo {
-        ToolInfo(Path path, String version) {
-            this.path = path;
-            this.version = new DottedVersion(version);
-        }
-
-        final Path path;
-        final DottedVersion version;
-    }
-
-    static Map<WixTool, ToolInfo> toolset() throws ConfigException {
-        Map<WixTool, ToolInfo> toolset = new HashMap<>();
-        for (var tool : values()) {
-            toolset.put(tool, tool.find());
-        }
-        return toolset;
-    }
-
-    ToolInfo find() throws ConfigException {
-        final Path toolFileName = IOUtils.addSuffix(
-                Path.of(name().toLowerCase()), ".exe");
-
-        String[] version = new String[1];
-        ConfigException reason = createToolValidator(toolFileName, version).get();
-        if (version[0] != null) {
-            if (reason == null) {
-                // Found in PATH.
-                return new ToolInfo(toolFileName, version[0]);
-            }
-
-            // Found in PATH, but something went wrong.
-            throw reason;
-        }
-
-        for (var dir : findWixInstallDirs()) {
-            Path path = dir.resolve(toolFileName);
-            if (path.toFile().exists()) {
-                reason = createToolValidator(path, version).get();
-                if (reason != null) {
-                    throw reason;
-                }
-                return new ToolInfo(path, version[0]);
-            }
-        }
-
-        throw reason;
-    }
-
-    private static Supplier<ConfigException> createToolValidator(Path toolPath,
-            String[] versionCtnr) {
-        return new ToolValidator(toolPath)
-                .setCommandLine("/?")
-                .setMinimalVersion(MINIMAL_VERSION)
-                .setToolNotFoundErrorHandler(
-                        (name, ex) -> new ConfigException(
-                                I18N.getString("error.no-wix-tools"),
-                                I18N.getString("error.no-wix-tools.advice")))
-                .setToolOldVersionErrorHandler(
-                        (name, version) -> new ConfigException(
-                                MessageFormat.format(I18N.getString(
-                                        "message.wrong-tool-version"), name,
-                                        version, MINIMAL_VERSION),
-                                I18N.getString("error.no-wix-tools.advice")))
-                .setVersionParser(output -> {
-                    versionCtnr[0] = "";
-                    String firstLineOfOutput = output.findFirst().orElse("");
-                    int separatorIdx = firstLineOfOutput.lastIndexOf(' ');
-                    if (separatorIdx == -1) {
-                        return null;
-                    }
-                    versionCtnr[0] = firstLineOfOutput.substring(separatorIdx + 1);
-                    return versionCtnr[0];
-                })::validate;
-    }
-
-    private final static DottedVersion MINIMAL_VERSION = DottedVersion.lazy("3.0");
-
-    static Path getSystemDir(String envVar, String knownDir) {
-        return Optional
-                .ofNullable(getEnvVariableAsPath(envVar))
-                .orElseGet(() -> Optional
-                        .ofNullable(getEnvVariableAsPath("SystemDrive"))
-                        .orElseGet(() -> Path.of("C:")).resolve(knownDir));
-    }
-
-    private static Path getEnvVariableAsPath(String envVar) {
-        String path = System.getenv(envVar);
-        if (path != null) {
-            try {
-                return Path.of(path);
-            } catch (InvalidPathException ex) {
-                Log.error(MessageFormat.format(I18N.getString(
-                        "error.invalid-envvar"), envVar));
-            }
-        }
-        return null;
-    }
-
-    private static List<Path> findWixInstallDirs() {
-        PathMatcher wixInstallDirMatcher = FileSystems.getDefault().getPathMatcher(
-                "glob:WiX Toolset v*");
-
-        Path programFiles = getSystemDir("ProgramFiles", "\\Program Files");
-        Path programFilesX86 = getSystemDir("ProgramFiles(x86)",
-                "\\Program Files (x86)");
-
-        // Returns list of WiX install directories ordered by WiX version number.
-        // Newer versions go first.
-        return Stream.of(programFiles, programFilesX86).map(path -> {
-            List<Path> result;
-            try (var paths = Files.walk(path, 1)) {
-                result = paths.collect(Collectors.toList());
-            } catch (IOException ex) {
-                Log.verbose(ex);
-                result = Collections.emptyList();
-            }
-            return result;
-        }).flatMap(List::stream)
-        .filter(path -> wixInstallDirMatcher.matches(path.getFileName()))
-        .sorted(Comparator.comparing(Path::getFileName).reversed())
-        .map(path -> path.resolve("bin"))
-        .collect(Collectors.toList());
-    }
-}
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_en.wxl	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="1252">
-  <String Id="message.install.dir.exist">The folder [INSTALLDIR] already exist. Would you like to install to that folder anyway?</String>
-  <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>
-</WixLocalization>
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="932">
-  <String Id="message.install.dir.exist">The folder [INSTALLDIR] already exist. Would you like to install to that folder anyway?</String>
-  <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>
-</WixLocalization>
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization" Codepage="936">
-  <String Id="message.install.dir.exist">The folder [INSTALLDIR] already exist. Would you like to install to that folder anyway?</String>
-  <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>
-</WixLocalization>
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinLauncher.template	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-CompanyName=COMPANY_NAME
-FileDescription=FILE_DESCRIPTION
-FileVersion=FILE_VERSION
-InternalName=INTERNAL_NAME
-LegalCopyright=LEGAL_COPYRIGHT
-OriginalFilename=ORIGINAL_FILENAME
-ProductName=PRODUCT_NAME
-ProductVersion=PRODUCT_VERSION
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-app.bundler.name=Windows Application Image
-exe.bundler.name=EXE Installer Package
-msi.bundler.name=MSI Installer Package
-
-param.menu-group.default=Unknown
-
-resource.executable-properties-template=Template for creating executable properties file
-resource.setup-icon=setup dialog icon
-resource.post-app-image-script=script to run after application image is populated
-resource.post-msi-script=script to run after msi file for exe installer is created
-resource.wxl-file-name=MsiInstallerStrings_en.wxl
-resource.main-wix-file=Main WiX project file
-resource.overrides-wix-file=Overrides 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.
-error.version-string-wrong-format=Version string is not compatible with MSI rules [{0}]
-error.version-string-wrong-format.advice=Set the bundler argument "{0}" according to these rules: https://msdn.microsoft.com/en-us/library/aa370859%28v\=VS.85%29.aspx .
-error.version-string-major-out-of-range=Major version must be in the range [0, 255]
-error.version-string-build-out-of-range=Build part of version must be in the range [0, 65535]
-error.version-string-minor-out-of-range=Minor version must be in the range [0, 255]
-error.version-string-part-not-number=Failed to convert version component to int
-error.version-swap=Failed to update version information for {0}
-error.invalid-envvar=Invalid value of {0} environment variable
-
-message.result-dir=Result application bundle: {0}.
-message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place.
-message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}".
-message.outputting-to-location=Generating EXE for installer to: {0}.
-message.output-location=Installer (.exe) saved to: {0}
-message.tool-version=Detected [{0}] version [{1}].
-message.creating-association-with-null-extension=Creating association with null extension.
-message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required.
-message.version-string-too-many-components=Version sting may have up to 3 components - major.minor.build .
-message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action.
-message.product-code=MSI ProductCode: {0}.
-message.upgrade-code=MSI UpgradeCode: {0}.
-message.preparing-msi-config=Preparing MSI config: {0}.
-message.generating-msi=Generating MSI: {0}.
-message.invalid.install.dir=Warning: Invalid install directory {0}. Install directory should be a relative sub-path under the default installation location such as "Program Files". Defaulting to application name "{1}".
-
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-app.bundler.name=Windows Application Image
-exe.bundler.name=EXE Installer Package
-msi.bundler.name=MSI Installer Package
-
-param.menu-group.default=Unknown
-
-resource.executable-properties-template=Template for creating executable properties file
-resource.setup-icon=setup dialog icon
-resource.post-app-image-script=script to run after application image is populated
-resource.post-msi-script=script to run after msi file for exe installer is created
-resource.wxl-file-name=MsiInstallerStrings_en.wxl
-resource.main-wix-file=Main WiX project file
-resource.overrides-wix-file=Overrides 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.
-error.version-string-wrong-format=Version string is not compatible with MSI rules [{0}]
-error.version-string-wrong-format.advice=Set the bundler argument "{0}" according to these rules: https://msdn.microsoft.com/en-us/library/aa370859%28v\=VS.85%29.aspx .
-error.version-string-major-out-of-range=Major version must be in the range [0, 255]
-error.version-string-build-out-of-range=Build part of version must be in the range [0, 65535]
-error.version-string-minor-out-of-range=Minor version must be in the range [0, 255]
-error.version-string-part-not-number=Failed to convert version component to int
-error.version-swap=Failed to update version information for {0}
-error.invalid-envvar=Invalid value of {0} environment variable
-
-message.result-dir=Result application bundle: {0}.
-message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place.
-message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}".
-message.outputting-to-location=Generating EXE for installer to: {0}.
-message.output-location=Installer (.exe) saved to: {0}
-message.tool-version=Detected [{0}] version [{1}].
-message.creating-association-with-null-extension=Creating association with null extension.
-message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required.
-message.version-string-too-many-components=Version sting may have up to 3 components - major.minor.build .
-message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action.
-message.product-code=MSI ProductCode: {0}.
-message.upgrade-code=MSI UpgradeCode: {0}.
-message.preparing-msi-config=Preparing MSI config: {0}.
-message.generating-msi=Generating MSI: {0}.
-message.invalid.install.dir=Warning: Invalid install directory {0}. Install directory should be a relative sub-path under the default installation location such as "Program Files". Defaulting to application name "{1}".
-
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-#
-# Copyright (c) 2017, 2019, 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.
-#
-#
-
-app.bundler.name=Windows Application Image
-exe.bundler.name=EXE Installer Package
-msi.bundler.name=MSI Installer Package
-
-param.menu-group.default=Unknown
-
-resource.executable-properties-template=Template for creating executable properties file
-resource.setup-icon=setup dialog icon
-resource.post-app-image-script=script to run after application image is populated
-resource.post-msi-script=script to run after msi file for exe installer is created
-resource.wxl-file-name=MsiInstallerStrings_en.wxl
-resource.main-wix-file=Main WiX project file
-resource.overrides-wix-file=Overrides 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.
-error.version-string-wrong-format=Version string is not compatible with MSI rules [{0}]
-error.version-string-wrong-format.advice=Set the bundler argument "{0}" according to these rules: https://msdn.microsoft.com/en-us/library/aa370859%28v\=VS.85%29.aspx .
-error.version-string-major-out-of-range=Major version must be in the range [0, 255]
-error.version-string-build-out-of-range=Build part of version must be in the range [0, 65535]
-error.version-string-minor-out-of-range=Minor version must be in the range [0, 255]
-error.version-string-part-not-number=Failed to convert version component to int
-error.version-swap=Failed to update version information for {0}
-error.invalid-envvar=Invalid value of {0} environment variable
-
-message.result-dir=Result application bundle: {0}.
-message.icon-not-ico=The specified icon "{0}" is not an ICO file and will not be used. The default icon will be used in it's place.
-message.potential.windows.defender.issue=Warning: Windows Defender may prevent jpackage from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}".
-message.outputting-to-location=Generating EXE for installer to: {0}.
-message.output-location=Installer (.exe) saved to: {0}
-message.tool-version=Detected [{0}] version [{1}].
-message.creating-association-with-null-extension=Creating association with null extension.
-message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required.
-message.version-string-too-many-components=Version sting may have up to 3 components - major.minor.build .
-message.use-wix36-features=WiX {0} detected. Enabling advanced cleanup action.
-message.product-code=MSI ProductCode: {0}.
-message.upgrade-code=MSI UpgradeCode: {0}.
-message.preparing-msi-config=Preparing MSI config: {0}.
-message.generating-msi=Generating MSI: {0}.
-message.invalid.install.dir=Warning: Invalid install directory {0}. Install directory should be a relative sub-path under the default installation location such as "Program Files". Defaulting to application name "{1}".
-
Binary file src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/java48.ico has changed
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/main.wxs	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
-     xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
-
-  <?ifdef JpIsSystemWide ?>
-    <?define JpInstallScope="perMachine"?>
-  <?else?>
-    <?define JpInstallScope="perUser"?>
-  <?endif?>
-
-  <?define JpProductLanguage=1033 ?>
-  <?define JpInstallerVersion=200 ?>
-  <?define JpCompressedMsi=yes ?>
-
-  <?include $(var.JpConfigDir)/overrides.wxi ?>
-
-  <Product
-    Id="$(var.JpProductCode)"
-    Name="$(var.JpAppName)"
-    Language="$(var.JpProductLanguage)"
-    Version="$(var.JpAppVersion)"
-    Manufacturer="$(var.JpAppVendor)"
-    UpgradeCode="$(var.JpProductUpgradeCode)">
-
-    <Package
-      Description="$(var.JpAppDescription)"
-      Manufacturer="$(var.JpAppVendor)"
-      InstallerVersion="$(var.JpInstallerVersion)"
-      Compressed="$(var.JpCompressedMsi)"
-      InstallScope="$(var.JpInstallScope)" Platform="x64"
-    />
-
-    <Media Id="1" Cabinet="Data.cab" EmbedCab="yes" />
-
-    <?ifdef JpAllowDowngrades ?>
-    <?ifdef JpAllowUpgrades ?>
-    <MajorUpgrade
-      AllowDowngrades="yes"
-      Disallow="no"
-    />
-    <?endif?>
-    <?endif?>
-
-    <?ifdef JpAllowDowngrades ?>
-    <?ifndef JpAllowUpgrades ?>
-    <MajorUpgrade
-      AllowDowngrades="yes"
-      Disallow="yes"
-      DisallowUpgradeErrorMessage="!(loc.DisallowUpgradeErrorMessage)"
-    />
-    <?endif?>
-    <?endif?>
-
-    <?ifndef JpAllowDowngrades ?>
-    <?ifdef JpAllowUpgrades ?>
-    <MajorUpgrade
-      AllowDowngrades="no"
-      Disallow="no"
-      DowngradeErrorMessage="!(loc.DowngradeErrorMessage)"
-    />
-    <?endif?>
-    <?endif?>
-
-    <?ifndef JpAllowDowngrades ?>
-    <?ifndef JpAllowUpgrades ?>
-    <MajorUpgrade
-      AllowDowngrades="no"
-      Disallow="yes"
-      DowngradeErrorMessage="!(loc.DowngradeErrorMessage)"
-      DisallowUpgradeErrorMessage="!(loc.DisallowUpgradeErrorMessage)"
-    />
-    <?endif?>
-    <?endif?>
-
-    <!-- Standard required root -->
-    <Directory Id="TARGETDIR" Name="SourceDir"/>
-
-    <Feature Id="DefaultFeature" Title="!(loc.MainFeatureTitle)" Level="1">
-      <ComponentGroupRef Id="Shortcuts"/>
-      <ComponentGroupRef Id="Files"/>
-      <ComponentGroupRef Id="FileAssociations"/>
-    </Feature>
-
-    <?ifdef JpInstallDirChooser ?>
-    <Binary Id="JpCaDll" SourceFile="wixhelper.dll"/>
-    <CustomAction Id="JpCheckInstallDir" BinaryKey="JpCaDll" DllEntry="CheckInstallDir" />
-    <?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?>
-
-  </Product>
-</Wix>
--- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/overrides.wxi	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Stub by design -->
-<Include/>
\ No newline at end of file
--- a/src/jdk.jpackage/windows/classes/module-info.java.extra	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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.
- */
-
-provides jdk.jpackage.internal.Bundler with
-    jdk.jpackage.internal.WinAppBundler,
-    jdk.jpackage.internal.WinExeBundler,
-    jdk.jpackage.internal.WinMsiBundler;
-
--- a/src/jdk.jpackage/windows/native/jpackageapplauncher/WinLauncher.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.
- */
-
-#include <Windows.h>
-#include <Shellapi.h>
-#include <locale.h>
-#include <tchar.h>
-#include <string>
-
-#define JPACKAGE_LIBRARY TEXT("applauncher.dll")
-
-typedef bool (*start_launcher)(int argc, TCHAR* argv[]);
-typedef void (*stop_launcher)();
-
-std::wstring GetTitle() {
-    std::wstring result;
-    wchar_t buffer[MAX_PATH];
-    GetModuleFileName(NULL, buffer, MAX_PATH - 1);
-    buffer[MAX_PATH - 1] = '\0';
-    result = buffer;
-    size_t slash = result.find_last_of('\\');
-
-    if (slash != std::wstring::npos)
-        result = result.substr(slash + 1, result.size() - slash - 1);
-
-    return result;
-}
-
-#ifdef LAUNCHERC
-int main(int argc0, char *argv0[]) {
-#else // LAUNCHERC
-int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-                       LPTSTR lpCmdLine, int nCmdShow) {
-#endif // LAUNCHERC
-    int result = 1;
-    TCHAR **argv;
-    int argc;
-
-    // [RT-31061] otherwise UI can be left in back of other windows.
-    ::AllowSetForegroundWindow(ASFW_ANY);
-
-    ::setlocale(LC_ALL, "en_US.utf8");
-    argv = CommandLineToArgvW(GetCommandLine(), &argc);
-
-    HMODULE library = ::LoadLibrary(JPACKAGE_LIBRARY);
-
-    if (library == NULL) {
-        std::wstring title = GetTitle();
-        std::wstring description = std::wstring(JPACKAGE_LIBRARY)
-                + std::wstring(TEXT(" not found."));
-        MessageBox(NULL, description.data(),
-                title.data(), MB_ICONERROR | MB_OK);
-    }
-    else {
-        start_launcher start =
-                (start_launcher)GetProcAddress(library, "start_launcher");
-        stop_launcher stop =
-                (stop_launcher)GetProcAddress(library, "stop_launcher");
-
-        if (start != NULL && stop != NULL) {
-            if (start(argc, argv) == true) {
-                result = 0;
-                stop();
-            }
-        }
-
-        ::FreeLibrary(library);
-    }
-
-    if (argv != NULL) {
-        LocalFree(argv);
-    }
-
-    return result;
-}
-
--- a/src/jdk.jpackage/windows/native/libapplauncher/DllMain.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include <windows.h>
-
-extern "C" {
-
-    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
-            LPVOID lpvReserved) {
-        return true;
-    }
-}
\ No newline at end of file
--- a/src/jdk.jpackage/windows/native/libapplauncher/FileAttribute.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef FILEATTRIBUTE_H
-#define FILEATTRIBUTE_H
-
-enum FileAttribute {
-    faArchive = FILE_ATTRIBUTE_ARCHIVE,
-    faCompressed = FILE_ATTRIBUTE_COMPRESSED,
-    faDevice = FILE_ATTRIBUTE_DEVICE,
-    faDirectory = FILE_ATTRIBUTE_DIRECTORY,
-    faEncrypted = FILE_ATTRIBUTE_ENCRYPTED,
-    faHidden = FILE_ATTRIBUTE_HIDDEN,
-    faNormal = FILE_ATTRIBUTE_NORMAL,
-    faNotContentIndexed = FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
-    faOffline = FILE_ATTRIBUTE_OFFLINE,
-    faSystem = FILE_ATTRIBUTE_SYSTEM,
-    faSymbolicLink = FILE_ATTRIBUTE_REPARSE_POINT,
-    faSparceFile = FILE_ATTRIBUTE_SPARSE_FILE,
-    faReadOnly = FILE_ATTRIBUTE_READONLY,
-    faTemporary = FILE_ATTRIBUTE_TEMPORARY,
-    faVirtual = FILE_ATTRIBUTE_VIRTUAL
-};
-
-#endif // FILEATTRIBUTE_H
-
--- a/src/jdk.jpackage/windows/native/libapplauncher/FilePath.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,468 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "FilePath.h"
-
-#include <algorithm>
-#include <list>
-#include <ShellAPI.h>
-
-bool FilePath::FileExists(const TString FileName) {
-    bool result = false;
-    WIN32_FIND_DATA FindFileData;
-    TString fileName = FixPathForPlatform(FileName);
-    HANDLE handle = FindFirstFile(fileName.data(), &FindFileData);
-
-    if (handle != INVALID_HANDLE_VALUE) {
-        if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
-            result = true;
-        }
-        else {
-            result = true;
-        }
-
-        FindClose(handle);
-    }
-    return result;
-}
-
-bool FilePath::DirectoryExists(const TString DirectoryName) {
-    bool result = false;
-    WIN32_FIND_DATA FindFileData;
-    TString directoryName = FixPathForPlatform(DirectoryName);
-    HANDLE handle = FindFirstFile(directoryName.data(), &FindFileData);
-
-    if (handle != INVALID_HANDLE_VALUE) {
-        if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
-            result = true;
-        }
-
-        FindClose(handle);
-    }
-    return result;
-}
-
-std::string GetLastErrorAsString() {
-    // Get the error message, if any.
-    DWORD errorMessageID = ::GetLastError();
-
-    if (errorMessageID == 0) {
-        return "No error message has been recorded";
-    }
-
-    LPSTR messageBuffer = NULL;
-    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
-            | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-            NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL,
-            SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
-
-    std::string message(messageBuffer, size);
-
-    // Free the buffer.
-    LocalFree(messageBuffer);
-
-    return message;
-}
-
-bool FilePath::DeleteFile(const TString FileName) {
-    bool result = false;
-
-    if (FileExists(FileName) == true) {
-        TString lFileName = FixPathForPlatform(FileName);
-        FileAttributes attributes(lFileName);
-
-        if (attributes.Contains(faReadOnly) == true) {
-            attributes.Remove(faReadOnly);
-        }
-
-        result = ::DeleteFile(lFileName.data()) == TRUE;
-    }
-
-    return result;
-}
-
-bool FilePath::DeleteDirectory(const TString DirectoryName) {
-    bool result = false;
-
-    if (DirectoryExists(DirectoryName) == true) {
-        SHFILEOPSTRUCTW fos = {0};
-        TString directoryName = FixPathForPlatform(DirectoryName);
-        DynamicBuffer<TCHAR> lDirectoryName(directoryName.size() + 2);
-        if (lDirectoryName.GetData() == NULL) {
-            return false;
-        }
-        memcpy(lDirectoryName.GetData(), directoryName.data(),
-                (directoryName.size() + 2) * sizeof(TCHAR));
-        lDirectoryName[directoryName.size() + 1] = NULL;
-        // Double null terminate for SHFileOperation.
-
-        // Delete the folder and everything inside.
-        fos.wFunc = FO_DELETE;
-        fos.pFrom = lDirectoryName.GetData();
-        fos.fFlags = FOF_NO_UI;
-        result = SHFileOperation(&fos) == 0;
-    }
-
-    return result;
-}
-
-TString FilePath::IncludeTrailingSeparator(const TString value) {
-    TString result = value;
-
-    if (value.size() > 0) {
-        TString::iterator i = result.end();
-        i--;
-
-        if (*i != TRAILING_PATHSEPARATOR) {
-            result += TRAILING_PATHSEPARATOR;
-        }
-    }
-
-    return result;
-}
-
-TString FilePath::IncludeTrailingSeparator(const char* value) {
-    TString lvalue = PlatformString(value).toString();
-    return IncludeTrailingSeparator(lvalue);
-}
-
-TString FilePath::IncludeTrailingSeparator(const wchar_t* value) {
-    TString lvalue = PlatformString(value).toString();
-    return IncludeTrailingSeparator(lvalue);
-}
-
-TString FilePath::ExtractFilePath(TString Path) {
-    TString result;
-    size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
-    if (slash != TString::npos)
-        result = Path.substr(0, slash);
-    return result;
-}
-
-TString FilePath::ExtractFileExt(TString Path) {
-    TString result;
-    size_t dot = Path.find_last_of('.');
-
-    if (dot != TString::npos) {
-        result  = Path.substr(dot, Path.size() - dot);
-    }
-
-    return result;
-}
-
-TString FilePath::ExtractFileName(TString Path) {
-    TString result;
-
-    size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
-    if (slash != TString::npos)
-        result = Path.substr(slash + 1, Path.size() - slash - 1);
-
-    return result;
-}
-
-TString FilePath::ChangeFileExt(TString Path, TString Extension) {
-    TString result;
-    size_t dot = Path.find_last_of('.');
-
-    if (dot != TString::npos) {
-        result = Path.substr(0, dot) + Extension;
-    }
-
-    if (result.empty() == true) {
-        result = Path;
-    }
-
-    return result;
-}
-
-TString FilePath::FixPathForPlatform(TString Path) {
-    TString result = Path;
-    std::replace(result.begin(), result.end(),
-            BAD_TRAILING_PATHSEPARATOR, TRAILING_PATHSEPARATOR);
-    // The maximum path that does not require long path prefix. On Windows the
-    // maximum path is 260 minus 1 (NUL) but for directories it is 260 minus
-    // 12 minus 1 (to allow for the creation of a 8.3 file in the directory).
-    const int maxPath = 247;
-    if (result.length() > maxPath &&
-        result.find(_T("\\\\?\\")) == TString::npos &&
-        result.find(_T("\\\\?\\UNC")) == TString::npos) {
-        const TString prefix(_T("\\\\"));
-        if (!result.compare(0, prefix.size(), prefix)) {
-            // UNC path, converting to UNC path in long notation
-            result = _T("\\\\?\\UNC") + result.substr(1, result.length());
-        } else {
-            // converting to non-UNC path in long notation
-            result = _T("\\\\?\\") + result;
-        }
-    }
-    return result;
-}
-
-TString FilePath::FixPathSeparatorForPlatform(TString Path) {
-    TString result = Path;
-    std::replace(result.begin(), result.end(),
-            BAD_PATH_SEPARATOR, PATH_SEPARATOR);
-    return result;
-}
-
-TString FilePath::PathSeparator() {
-    TString result;
-    result = PATH_SEPARATOR;
-    return result;
-}
-
-bool FilePath::CreateDirectory(TString Path, bool ownerOnly) {
-    bool result = false;
-
-    std::list<TString> paths;
-    TString lpath = Path;
-
-    while (lpath.empty() == false && DirectoryExists(lpath) == false) {
-        paths.push_front(lpath);
-        lpath = ExtractFilePath(lpath);
-    }
-
-    for (std::list<TString>::iterator iterator = paths.begin();
-            iterator != paths.end(); iterator++) {
-        lpath = *iterator;
-
-        if (_wmkdir(lpath.data()) == 0) {
-            result = true;
-        } else {
-            result = false;
-            break;
-        }
-    }
-
-    return result;
-}
-
-void FilePath::ChangePermissions(TString FileName, bool ownerOnly) {
-}
-
-#include <algorithm>
-
-FileAttributes::FileAttributes(const TString FileName, bool FollowLink) {
-    FFileName = FileName;
-    FFollowLink = FollowLink;
-    ReadAttributes();
-}
-
-bool FileAttributes::WriteAttributes() {
-    bool result = false;
-
-    DWORD attributes = 0;
-
-    for (std::vector<FileAttribute>::const_iterator iterator =
-            FAttributes.begin();
-        iterator != FAttributes.end(); iterator++) {
-        switch (*iterator) {
-            case faArchive: {
-                attributes = attributes & FILE_ATTRIBUTE_ARCHIVE;
-                break;
-            }
-            case faCompressed: {
-                attributes = attributes & FILE_ATTRIBUTE_COMPRESSED;
-                break;
-            }
-            case faDevice: {
-                attributes = attributes & FILE_ATTRIBUTE_DEVICE;
-                break;
-            }
-            case faDirectory: {
-                attributes = attributes & FILE_ATTRIBUTE_DIRECTORY;
-                break;
-            }
-            case faEncrypted: {
-                attributes = attributes & FILE_ATTRIBUTE_ENCRYPTED;
-                break;
-            }
-            case faHidden: {
-                attributes = attributes & FILE_ATTRIBUTE_HIDDEN;
-                break;
-            }
-            case faNormal: {
-                attributes = attributes & FILE_ATTRIBUTE_NORMAL;
-                break;
-            }
-            case faNotContentIndexed: {
-                attributes = attributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
-                break;
-            }
-            case faOffline: {
-                attributes = attributes & FILE_ATTRIBUTE_OFFLINE;
-                break;
-            }
-            case faSystem: {
-                attributes = attributes & FILE_ATTRIBUTE_SYSTEM;
-                break;
-            }
-            case faSymbolicLink: {
-                attributes = attributes & FILE_ATTRIBUTE_REPARSE_POINT;
-                break;
-            }
-            case faSparceFile: {
-                attributes = attributes & FILE_ATTRIBUTE_SPARSE_FILE;
-                break;
-            }
-            case faReadOnly: {
-                attributes = attributes & FILE_ATTRIBUTE_READONLY;
-                break;
-            }
-            case faTemporary: {
-                attributes = attributes & FILE_ATTRIBUTE_TEMPORARY;
-                break;
-            }
-            case faVirtual: {
-                attributes = attributes & FILE_ATTRIBUTE_VIRTUAL;
-                break;
-            }
-        }
-    }
-
-    if (::SetFileAttributes(FFileName.data(), attributes) != 0) {
-        result = true;
-    }
-
-    return result;
-}
-
-#define S_ISRUSR(m)    (((m) & S_IRWXU) == S_IRUSR)
-#define S_ISWUSR(m)    (((m) & S_IRWXU) == S_IWUSR)
-#define S_ISXUSR(m)    (((m) & S_IRWXU) == S_IXUSR)
-
-#define S_ISRGRP(m)    (((m) & S_IRWXG) == S_IRGRP)
-#define S_ISWGRP(m)    (((m) & S_IRWXG) == S_IWGRP)
-#define S_ISXGRP(m)    (((m) & S_IRWXG) == S_IXGRP)
-
-#define S_ISROTH(m)    (((m) & S_IRWXO) == S_IROTH)
-#define S_ISWOTH(m)    (((m) & S_IRWXO) == S_IWOTH)
-#define S_ISXOTH(m)    (((m) & S_IRWXO) == S_IXOTH)
-
-bool FileAttributes::ReadAttributes() {
-    bool result = false;
-
-    DWORD attributes = ::GetFileAttributes(FFileName.data());
-
-    if (attributes != INVALID_FILE_ATTRIBUTES) {
-        result = true;
-
-        if (attributes | FILE_ATTRIBUTE_ARCHIVE) {
-            FAttributes.push_back(faArchive);
-        }
-        if (attributes | FILE_ATTRIBUTE_COMPRESSED) {
-            FAttributes.push_back(faCompressed);
-        }
-        if (attributes | FILE_ATTRIBUTE_DEVICE) {
-            FAttributes.push_back(faDevice);
-        }
-        if (attributes | FILE_ATTRIBUTE_DIRECTORY) {
-            FAttributes.push_back(faDirectory);
-        }
-        if (attributes | FILE_ATTRIBUTE_ENCRYPTED) {
-            FAttributes.push_back(faEncrypted);
-        }
-        if (attributes | FILE_ATTRIBUTE_HIDDEN) {
-            FAttributes.push_back(faHidden);
-        }
-        if (attributes | FILE_ATTRIBUTE_NORMAL) {
-            FAttributes.push_back(faNormal);
-        }
-        if (attributes | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) {
-            FAttributes.push_back(faNotContentIndexed);
-        }
-        if (attributes | FILE_ATTRIBUTE_SYSTEM) {
-            FAttributes.push_back(faSystem);
-        }
-        if (attributes | FILE_ATTRIBUTE_OFFLINE) {
-            FAttributes.push_back(faOffline);
-        }
-        if (attributes | FILE_ATTRIBUTE_REPARSE_POINT) {
-            FAttributes.push_back(faSymbolicLink);
-        }
-        if (attributes | FILE_ATTRIBUTE_SPARSE_FILE) {
-            FAttributes.push_back(faSparceFile);
-        }
-        if (attributes | FILE_ATTRIBUTE_READONLY ) {
-            FAttributes.push_back(faReadOnly);
-        }
-        if (attributes | FILE_ATTRIBUTE_TEMPORARY) {
-            FAttributes.push_back(faTemporary);
-        }
-        if (attributes | FILE_ATTRIBUTE_VIRTUAL) {
-            FAttributes.push_back(faVirtual);
-        }
-    }
-
-    return result;
-}
-
-bool FileAttributes::Valid(const FileAttribute Value) {
-    bool result = false;
-
-    switch (Value) {
-        case faHidden:
-        case faReadOnly: {
-            result = true;
-            break;
-        }
-        default:
-            break;
-    }
-
-    return result;
-}
-
-void FileAttributes::Append(FileAttribute Value) {
-    if (Valid(Value) == true) {
-        FAttributes.push_back(Value);
-        WriteAttributes();
-    }
-}
-
-bool FileAttributes::Contains(FileAttribute Value) {
-    bool result = false;
-
-    std::vector<FileAttribute>::const_iterator iterator =
-            std::find(FAttributes.begin(), FAttributes.end(), Value);
-
-    if (iterator != FAttributes.end()) {
-        result = true;
-    }
-
-    return result;
-}
-
-void FileAttributes::Remove(FileAttribute Value) {
-    if (Valid(Value) == true) {
-        std::vector<FileAttribute>::iterator iterator =
-            std::find(FAttributes.begin(), FAttributes.end(), Value);
-
-        if (iterator != FAttributes.end()) {
-            FAttributes.erase(iterator);
-            WriteAttributes();
-        }
-    }
-}
--- a/src/jdk.jpackage/windows/native/libapplauncher/PlatformDefs.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef PLATFORM_DEFS_H
-#define PLATFORM_DEFS_H
-
-// Define Windows compatibility requirements XP or later
-#define WINVER 0x0600
-#define _WIN32_WINNT 0x0600
-
-#include <Windows.h>
-#include <tchar.h>
-#include <shlobj.h>
-#include <direct.h>
-#include <process.h>
-#include <malloc.h>
-#include <string>
-
-using namespace std;
-
-#ifndef WINDOWS
-#define WINDOWS
-#endif
-
-typedef std::wstring TString;
-#define StringLength wcslen
-
-#define TRAILING_PATHSEPARATOR '\\'
-#define BAD_TRAILING_PATHSEPARATOR '/'
-#define PATH_SEPARATOR ';'
-#define BAD_PATH_SEPARATOR ':'
-
-typedef ULONGLONG TPlatformNumber;
-typedef DWORD TProcessID;
-
-typedef void* Module;
-typedef void* Procedure;
-
-#endif // PLATFORM_DEFS_H
--- a/src/jdk.jpackage/windows/native/libapplauncher/WindowsPlatform.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,759 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#include "Platform.h"
-
-#include "JavaVirtualMachine.h"
-#include "WindowsPlatform.h"
-#include "Package.h"
-#include "Helpers.h"
-#include "PlatformString.h"
-#include "Macros.h"
-
-#include <map>
-#include <vector>
-#include <regex>
-#include <fstream>
-#include <locale>
-#include <codecvt>
-
-using namespace std;
-
-#define WINDOWS_JPACKAGE_TMP_DIR \
-        L"\\AppData\\Local\\Java\\JPackage\\tmp"
-
-class Registry {
-private:
-    HKEY FKey;
-    HKEY FOpenKey;
-    bool FOpen;
-
-public:
-
-    Registry(HKEY Key) {
-        FOpen = false;
-        FKey = Key;
-    }
-
-    ~Registry() {
-        Close();
-    }
-
-    void Close() {
-        if (FOpen == true) {
-            RegCloseKey(FOpenKey);
-        }
-    }
-
-    bool Open(TString SubKey) {
-        bool result = false;
-        Close();
-
-        if (RegOpenKeyEx(FKey, SubKey.data(), 0, KEY_READ, &FOpenKey) ==
-                ERROR_SUCCESS) {
-            result = true;
-        }
-
-        return result;
-    }
-
-    std::list<TString> GetKeys() {
-        std::list<TString> result;
-        DWORD count;
-
-        if (RegQueryInfoKey(FOpenKey, NULL, NULL, NULL, NULL, NULL, NULL,
-                &count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
-
-            DWORD length = 255;
-            DynamicBuffer<TCHAR> buffer(length);
-            if (buffer.GetData() == NULL) {
-                return result;
-            }
-
-            for (unsigned int index = 0; index < count; index++) {
-                buffer.Zero();
-                DWORD status = RegEnumValue(FOpenKey, index, buffer.GetData(),
-                        &length, NULL, NULL, NULL, NULL);
-
-                while (status == ERROR_MORE_DATA) {
-                    length = length * 2;
-                    if (!buffer.Resize(length)) {
-                        return result;
-                    }
-                    status = RegEnumValue(FOpenKey, index, buffer.GetData(),
-                            &length, NULL, NULL, NULL, NULL);
-                }
-
-                if (status == ERROR_SUCCESS) {
-                    TString value = buffer.GetData();
-                    result.push_back(value);
-                }
-            }
-        }
-
-        return result;
-    }
-
-    TString ReadString(TString Name) {
-        TString result;
-        DWORD length;
-        DWORD dwRet;
-        DynamicBuffer<wchar_t> buffer(0);
-        length = 0;
-
-        dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, NULL,
-                &length);
-        if (dwRet == ERROR_MORE_DATA || dwRet == 0) {
-            if (!buffer.Resize(length + 1)) {
-                return result;
-            }
-            dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL,
-                    (LPBYTE) buffer.GetData(), &length);
-            result = buffer.GetData();
-        }
-
-        return result;
-    }
-};
-
-WindowsPlatform::WindowsPlatform(void) : Platform() {
-    FMainThread = ::GetCurrentThreadId();
-}
-
-WindowsPlatform::~WindowsPlatform(void) {
-}
-
-TString WindowsPlatform::GetPackageAppDirectory() {
-    return FilePath::IncludeTrailingSeparator(
-            GetPackageRootDirectory()) + _T("app");
-}
-
-TString WindowsPlatform::GetPackageLauncherDirectory() {
-    return  GetPackageRootDirectory();
-}
-
-TString WindowsPlatform::GetPackageRuntimeBinDirectory() {
-    return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory()) + _T("runtime\\bin");
-}
-
-TCHAR* WindowsPlatform::ConvertStringToFileSystemString(TCHAR* Source,
-        bool &release) {
-    // Not Implemented.
-    return NULL;
-}
-
-TCHAR* WindowsPlatform::ConvertFileSystemStringToString(TCHAR* Source,
-        bool &release) {
-    // Not Implemented.
-    return NULL;
-}
-
-TString WindowsPlatform::GetPackageRootDirectory() {
-    TString result;
-    TString filename = GetModuleFileName();
-    return FilePath::ExtractFilePath(filename);
-}
-
-TString WindowsPlatform::GetAppDataDirectory() {
-    TString result;
-    TCHAR path[MAX_PATH];
-
-    if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path) == S_OK) {
-        result = path;
-    }
-
-    return result;
-}
-
-TString WindowsPlatform::GetAppName() {
-    TString result = GetModuleFileName();
-    result = FilePath::ExtractFileName(result);
-    result = FilePath::ChangeFileExt(result, _T(""));
-    return result;
-}
-
-void WindowsPlatform::ShowMessage(TString title, TString description) {
-    MessageBox(NULL, description.data(),
-            !title.empty() ? title.data() : description.data(),
-            MB_ICONERROR | MB_OK);
-}
-
-void WindowsPlatform::ShowMessage(TString description) {
-    TString appname = GetModuleFileName();
-    appname = FilePath::ExtractFileName(appname);
-    MessageBox(NULL, description.data(), appname.data(), MB_ICONERROR | MB_OK);
-}
-
-MessageResponse WindowsPlatform::ShowResponseMessage(TString title,
-        TString description) {
-    MessageResponse result = mrCancel;
-
-    if (::MessageBox(NULL, description.data(), title.data(), MB_OKCANCEL) ==
-            IDOK) {
-        result = mrOK;
-    }
-
-    return result;
-}
-
-TString WindowsPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) {
-    TString result = FilePath::IncludeTrailingSeparator(RuntimePath) +
-            _T("jre\\bin\\jli.dll");
-
-    if (FilePath::FileExists(result) == false) {
-        result = FilePath::IncludeTrailingSeparator(RuntimePath) +
-                _T("bin\\jli.dll");
-    }
-
-    return result;
-}
-
-ISectionalPropertyContainer* WindowsPlatform::GetConfigFile(TString FileName) {
-    IniFile *result = new IniFile();
-    if (result == NULL) {
-        return NULL;
-    }
-
-    result->LoadFromFile(FileName);
-
-    return result;
-}
-
-TString WindowsPlatform::GetModuleFileName() {
-    TString result;
-    DynamicBuffer<wchar_t> buffer(MAX_PATH);
-    if (buffer.GetData() == NULL) {
-        return result;
-    }
-
-    ::GetModuleFileName(NULL, buffer.GetData(),
-            static_cast<DWORD> (buffer.GetSize()));
-
-    while (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
-        if (!buffer.Resize(buffer.GetSize() * 2)) {
-            return result;
-        }
-        ::GetModuleFileName(NULL, buffer.GetData(),
-                static_cast<DWORD> (buffer.GetSize()));
-    }
-
-    result = buffer.GetData();
-    return result;
-}
-
-Module WindowsPlatform::LoadLibrary(TString FileName) {
-    return ::LoadLibrary(FileName.data());
-}
-
-void WindowsPlatform::FreeLibrary(Module AModule) {
-    ::FreeLibrary((HMODULE) AModule);
-}
-
-Procedure WindowsPlatform::GetProcAddress(Module AModule,
-        std::string MethodName) {
-    return ::GetProcAddress((HMODULE) AModule, MethodName.c_str());
-}
-
-bool WindowsPlatform::IsMainThread() {
-    bool result = (FMainThread == ::GetCurrentThreadId());
-    return result;
-}
-
-TString WindowsPlatform::GetTempDirectory() {
-    TString result;
-    PWSTR userDir = 0;
-
-    if (SUCCEEDED(SHGetKnownFolderPath(
-            FOLDERID_Profile,
-            0,
-            NULL,
-            &userDir))) {
-        result = userDir;
-        result += WINDOWS_JPACKAGE_TMP_DIR;
-        CoTaskMemFree(userDir);
-    }
-
-    return result;
-}
-
-static BOOL CALLBACK enumWindows(HWND winHandle, LPARAM lParam) {
-    DWORD pid = (DWORD) lParam, wPid = 0;
-    GetWindowThreadProcessId(winHandle, &wPid);
-    if (pid == wPid) {
-        SetForegroundWindow(winHandle);
-        return FALSE;
-    }
-    return TRUE;
-}
-
-TPlatformNumber WindowsPlatform::GetMemorySize() {
-    SYSTEM_INFO si;
-    GetSystemInfo(&si);
-    size_t result = (size_t) si.lpMaximumApplicationAddress;
-    result = result / 1048576; // Convert from bytes to megabytes.
-    return result;
-}
-
-std::vector<TString> FilterList(std::vector<TString> &Items,
-        std::wregex Pattern) {
-    std::vector<TString> result;
-
-    for (std::vector<TString>::iterator it = Items.begin();
-            it != Items.end(); ++it) {
-        TString item = *it;
-        std::wsmatch match;
-
-        if (std::regex_search(item, match, Pattern)) {
-            result.push_back(item);
-        }
-    }
-    return result;
-}
-
-Process* WindowsPlatform::CreateProcess() {
-    return new WindowsProcess();
-}
-
-void WindowsPlatform::InitStreamLocale(wios *stream) {
-    const std::locale empty_locale = std::locale::empty();
-    const std::locale utf8_locale =
-                std::locale(empty_locale, new std::codecvt_utf8<wchar_t>());
-    stream->imbue(utf8_locale);
-}
-
-void WindowsPlatform::addPlatformDependencies(JavaLibrary *pJavaLibrary) {
-    if (pJavaLibrary == NULL) {
-        return;
-    }
-
-    if (FilePath::FileExists(_T("msvcr100.dll")) == true) {
-        pJavaLibrary->AddDependency(_T("msvcr100.dll"));
-    }
-
-    TString runtimeBin = GetPackageRuntimeBinDirectory();
-    SetDllDirectory(runtimeBin.c_str());
-}
-
-void Platform::CopyString(char *Destination,
-        size_t NumberOfElements, const char *Source) {
-    strcpy_s(Destination, NumberOfElements, Source);
-
-    if (NumberOfElements > 0) {
-        Destination[NumberOfElements - 1] = '\0';
-    }
-}
-
-void Platform::CopyString(wchar_t *Destination,
-        size_t NumberOfElements, const wchar_t *Source) {
-    wcscpy_s(Destination, NumberOfElements, Source);
-
-    if (NumberOfElements > 0) {
-        Destination[NumberOfElements - 1] = '\0';
-    }
-}
-
-// Owner must free the return value.
-MultibyteString Platform::WideStringToMultibyteString(
-        const wchar_t* value) {
-    MultibyteString result;
-    size_t count = 0;
-
-    if (value == NULL) {
-        return result;
-    }
-
-    count = WideCharToMultiByte(CP_UTF8, 0, value, -1, NULL, 0, NULL, NULL);
-
-    if (count > 0) {
-        result.data = new char[count + 1];
-        result.length = WideCharToMultiByte(CP_UTF8, 0, value, -1,
-                result.data, (int)count, NULL, NULL);
-    }
-
-    return result;
-}
-
-// Owner must free the return value.
-WideString Platform::MultibyteStringToWideString(const char* value) {
-    WideString result;
-    size_t count = 0;
-
-    if (value == NULL) {
-        return result;
-    }
-
-    mbstowcs_s(&count, NULL, 0, value, _TRUNCATE);
-
-    if (count > 0) {
-        result.data = new wchar_t[count + 1];
-        mbstowcs_s(&result.length, result.data, count, value, count);
-    }
-
-    return result;
-}
-
-FileHandle::FileHandle(std::wstring FileName) {
-    FHandle = ::CreateFile(FileName.data(), GENERIC_READ, FILE_SHARE_READ,
-            NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
-}
-
-FileHandle::~FileHandle() {
-    if (IsValid() == true) {
-        ::CloseHandle(FHandle);
-    }
-}
-
-bool FileHandle::IsValid() {
-    return FHandle != INVALID_HANDLE_VALUE;
-}
-
-HANDLE FileHandle::GetHandle() {
-    return FHandle;
-}
-
-FileMappingHandle::FileMappingHandle(HANDLE FileHandle) {
-    FHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
-}
-
-bool FileMappingHandle::IsValid() {
-    return FHandle != NULL;
-}
-
-FileMappingHandle::~FileMappingHandle() {
-    if (IsValid() == true) {
-        ::CloseHandle(FHandle);
-    }
-}
-
-HANDLE FileMappingHandle::GetHandle() {
-    return FHandle;
-}
-
-FileData::FileData(HANDLE Handle) {
-    FBaseAddress = ::MapViewOfFile(Handle, FILE_MAP_READ, 0, 0, 0);
-}
-
-FileData::~FileData() {
-    if (IsValid() == true) {
-        ::UnmapViewOfFile(FBaseAddress);
-    }
-}
-
-bool FileData::IsValid() {
-    return FBaseAddress != NULL;
-}
-
-LPVOID FileData::GetBaseAddress() {
-    return FBaseAddress;
-}
-
-WindowsLibrary::WindowsLibrary(std::wstring FileName) {
-    FFileName = FileName;
-}
-
-std::vector<TString> WindowsLibrary::GetImports() {
-    std::vector<TString> result;
-    FileHandle library(FFileName);
-
-    if (library.IsValid() == true) {
-        FileMappingHandle mapping(library.GetHandle());
-
-        if (mapping.IsValid() == true) {
-            FileData fileData(mapping.GetHandle());
-
-            if (fileData.IsValid() == true) {
-                PIMAGE_DOS_HEADER dosHeader =
-                        (PIMAGE_DOS_HEADER) fileData.GetBaseAddress();
-                PIMAGE_FILE_HEADER pImgFileHdr =
-                        (PIMAGE_FILE_HEADER) fileData.GetBaseAddress();
-                if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
-                    result = DumpPEFile(dosHeader);
-                }
-            }
-        }
-    }
-
-    return result;
-}
-
-// Given an RVA, look up the section header that encloses it and return a
-// pointer to its IMAGE_SECTION_HEADER
-
-PIMAGE_SECTION_HEADER WindowsLibrary::GetEnclosingSectionHeader(DWORD rva,
-        PIMAGE_NT_HEADERS pNTHeader) {
-    PIMAGE_SECTION_HEADER result = 0;
-    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
-
-    for (unsigned index = 0; index < pNTHeader->FileHeader.NumberOfSections;
-            index++, section++) {
-        // Is the RVA is within this section?
-        if ((rva >= section->VirtualAddress) &&
-                (rva < (section->VirtualAddress + section->Misc.VirtualSize))) {
-            result = section;
-        }
-    }
-
-    return result;
-}
-
-LPVOID WindowsLibrary::GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader,
-        DWORD imageBase) {
-    LPVOID result = 0;
-    PIMAGE_SECTION_HEADER pSectionHdr = GetEnclosingSectionHeader(rva,
-            pNTHeader);
-
-    if (pSectionHdr != NULL) {
-        INT delta = (INT) (
-                pSectionHdr->VirtualAddress - pSectionHdr->PointerToRawData);
-        DWORD_PTR dwp = (DWORD_PTR) (imageBase + rva - delta);
-        result = reinterpret_cast<LPVOID> (dwp); // VS2017 - FIXME
-    }
-
-    return result;
-}
-
-std::vector<TString> WindowsLibrary::GetImportsSection(DWORD base,
-        PIMAGE_NT_HEADERS pNTHeader) {
-    std::vector<TString> result;
-
-    // Look up where the imports section is located. Normally in
-    // the .idata section,
-    // but not necessarily so. Therefore, grab the RVA from the data dir.
-    DWORD importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[
-            IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
-
-    if (importsStartRVA != NULL) {
-        // Get the IMAGE_SECTION_HEADER that contains the imports. This is
-        // usually the .idata section, but doesn't have to be.
-        PIMAGE_SECTION_HEADER pSection =
-                GetEnclosingSectionHeader(importsStartRVA, pNTHeader);
-
-        if (pSection != NULL) {
-            PIMAGE_IMPORT_DESCRIPTOR importDesc =
-                    (PIMAGE_IMPORT_DESCRIPTOR) GetPtrFromRVA(
-                    importsStartRVA, pNTHeader, base);
-
-            if (importDesc != NULL) {
-                while (true) {
-                    // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR
-                    if ((importDesc->TimeDateStamp == 0) &&
-                            (importDesc->Name == 0)) {
-                        break;
-                    }
-
-                    std::string filename = (char*) GetPtrFromRVA(
-                            importDesc->Name, pNTHeader, base);
-                    result.push_back(PlatformString(filename));
-                    importDesc++; // advance to next IMAGE_IMPORT_DESCRIPTOR
-                }
-            }
-        }
-    }
-
-    return result;
-}
-
-std::vector<TString> WindowsLibrary::DumpPEFile(PIMAGE_DOS_HEADER dosHeader) {
-    std::vector<TString> result;
-    // all of this is VS2017 - FIXME
-    DWORD_PTR dwDosHeaders = reinterpret_cast<DWORD_PTR> (dosHeader);
-    DWORD_PTR dwPIHeaders = dwDosHeaders + (DWORD) (dosHeader->e_lfanew);
-
-    PIMAGE_NT_HEADERS pNTHeader =
-            reinterpret_cast<PIMAGE_NT_HEADERS> (dwPIHeaders);
-
-    // Verify that the e_lfanew field gave us a reasonable
-    // pointer and the PE signature.
-    // TODO: To really fix JDK-8131321 this condition needs to be changed.
-    // There is a matching change
-    // in JavaVirtualMachine.cpp that also needs to be changed.
-    if (pNTHeader->Signature == IMAGE_NT_SIGNATURE) {
-        DWORD base = (DWORD) (dwDosHeaders);
-        result = GetImportsSection(base, pNTHeader);
-    }
-
-    return result;
-}
-
-#include <TlHelp32.h>
-
-WindowsJob::WindowsJob() {
-    FHandle = NULL;
-}
-
-WindowsJob::~WindowsJob() {
-    if (FHandle != NULL) {
-        CloseHandle(FHandle);
-    }
-}
-
-HANDLE WindowsJob::GetHandle() {
-    if (FHandle == NULL) {
-        FHandle = CreateJobObject(NULL, NULL); // GLOBAL
-
-        if (FHandle == NULL) {
-            ::MessageBox(0, _T("Could not create job object"),
-                    _T("TEST"), MB_OK);
-        } else {
-            JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
-
-            // Configure all child processes associated with
-            // the job to terminate when the
-            jeli.BasicLimitInformation.LimitFlags =
-                    JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
-            if (0 == SetInformationJobObject(FHandle,
-                    JobObjectExtendedLimitInformation, &jeli, sizeof (jeli))) {
-                ::MessageBox(0, _T("Could not SetInformationJobObject"),
-                        _T("TEST"), MB_OK);
-            }
-        }
-    }
-
-    return FHandle;
-}
-
-// Initialize static member of WindowsProcess
-WindowsJob WindowsProcess::FJob;
-
-WindowsProcess::WindowsProcess() : Process() {
-    FRunning = false;
-}
-
-WindowsProcess::~WindowsProcess() {
-    Terminate();
-}
-
-void WindowsProcess::Cleanup() {
-    CloseHandle(FProcessInfo.hProcess);
-    CloseHandle(FProcessInfo.hThread);
-}
-
-bool WindowsProcess::IsRunning() {
-    bool result = false;
-
-    HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
-    if (handle == INVALID_HANDLE_VALUE) {
-        return false;
-    }
-
-    PROCESSENTRY32 process = {0};
-    process.dwSize = sizeof (process);
-
-    if (::Process32First(handle, &process)) {
-        do {
-            if (process.th32ProcessID == FProcessInfo.dwProcessId) {
-                result = true;
-                break;
-            }
-        } while (::Process32Next(handle, &process));
-    }
-
-    CloseHandle(handle);
-
-    return result;
-}
-
-bool WindowsProcess::Terminate() {
-    bool result = false;
-
-    if (IsRunning() == true && FRunning == true) {
-        FRunning = false;
-    }
-
-    return result;
-}
-
-bool WindowsProcess::Execute(const TString Application,
-        const std::vector<TString> Arguments, bool AWait) {
-    bool result = false;
-
-    if (FRunning == false) {
-        FRunning = true;
-
-        STARTUPINFO startupInfo;
-        ZeroMemory(&startupInfo, sizeof (startupInfo));
-        startupInfo.cb = sizeof (startupInfo);
-        ZeroMemory(&FProcessInfo, sizeof (FProcessInfo));
-
-        TString command = Application;
-
-        for (std::vector<TString>::const_iterator iterator = Arguments.begin();
-                iterator != Arguments.end(); iterator++) {
-            command += TString(_T(" ")) + *iterator;
-        }
-
-        if (::CreateProcess(Application.data(), (wchar_t*)command.data(), NULL,
-                NULL, FALSE, 0, NULL, NULL, &startupInfo, &FProcessInfo)
-                == FALSE) {
-            TString message = PlatformString::Format(
-                    _T("Error: Unable to create process %s"),
-                    Application.data());
-            throw Exception(message);
-        } else {
-            if (FJob.GetHandle() != NULL) {
-                if (::AssignProcessToJobObject(FJob.GetHandle(),
-                        FProcessInfo.hProcess) == 0) {
-                    // Failed to assign process to job. It doesn't prevent
-                    // anything from continuing so continue.
-                }
-            }
-
-            // Wait until child process exits.
-            if (AWait == true) {
-                Wait();
-                // Close process and thread handles.
-                Cleanup();
-            }
-        }
-    }
-
-    return result;
-}
-
-bool WindowsProcess::Wait() {
-    bool result = false;
-
-    WaitForSingleObject(FProcessInfo.hProcess, INFINITE);
-    return result;
-}
-
-TProcessID WindowsProcess::GetProcessID() {
-    return FProcessInfo.dwProcessId;
-}
-
-bool WindowsProcess::ReadOutput() {
-    bool result = false;
-    // TODO implement
-    return result;
-}
-
-void WindowsProcess::SetInput(TString Value) {
-    // TODO implement
-}
-
-std::list<TString> WindowsProcess::GetOutput() {
-    ReadOutput();
-    return Process::GetOutput();
-}
--- a/src/jdk.jpackage/windows/native/libapplauncher/WindowsPlatform.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2014, 2019, 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.
- */
-
-#ifndef WINDOWSPLATFORM_H
-#define WINDOWSPLATFORM_H
-
-#include <Windows.h>
-#include "Platform.h"
-
-class WindowsPlatform : virtual public Platform {
-private:
-    DWORD FMainThread;
-
-public:
-    WindowsPlatform(void);
-    virtual ~WindowsPlatform(void);
-
-    virtual TCHAR* ConvertStringToFileSystemString(TCHAR* Source,
-            bool &release);
-    virtual TCHAR* ConvertFileSystemStringToString(TCHAR* Source,
-            bool &release);
-
-    virtual void ShowMessage(TString title, TString description);
-    virtual void ShowMessage(TString description);
-    virtual MessageResponse ShowResponseMessage(TString title,
-            TString description);
-
-    virtual TString GetPackageRootDirectory();
-    virtual TString GetAppDataDirectory();
-    virtual TString GetAppName();
-    virtual TString GetBundledJavaLibraryFileName(TString RuntimePath);
-    TString GetPackageAppDirectory();
-    TString GetPackageLauncherDirectory();
-    TString GetPackageRuntimeBinDirectory();
-
-    virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
-
-    virtual TString GetModuleFileName();
-    virtual Module LoadLibrary(TString FileName);
-    virtual void FreeLibrary(Module AModule);
-    virtual Procedure GetProcAddress(Module AModule, std::string MethodName);
-
-    virtual Process* CreateProcess();
-
-    virtual bool IsMainThread();
-    virtual TPlatformNumber GetMemorySize();
-
-    virtual TString GetTempDirectory();
-    void InitStreamLocale(wios *stream);
-    void addPlatformDependencies(JavaLibrary *pJavaLibrary);
-};
-
-class FileHandle {
-private:
-    HANDLE FHandle;
-
-public:
-    FileHandle(std::wstring FileName);
-    ~FileHandle();
-
-    bool IsValid();
-    HANDLE GetHandle();
-};
-
-
-class FileMappingHandle {
-private:
-    HANDLE FHandle;
-
-public:
-    FileMappingHandle(HANDLE FileHandle);
-    ~FileMappingHandle();
-
-    bool IsValid();
-    HANDLE GetHandle();
-};
-
-
-class FileData {
-private:
-    LPVOID FBaseAddress;
-
-public:
-    FileData(HANDLE Handle);
-    ~FileData();
-
-    bool IsValid();
-    LPVOID GetBaseAddress();
-};
-
-
-class WindowsLibrary {
-private:
-    TString FFileName;
-
-    // Given an RVA, look up the section header that encloses it and return a
-    // pointer to its IMAGE_SECTION_HEADER
-    static PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva,
-            PIMAGE_NT_HEADERS pNTHeader);
-    static LPVOID GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader,
-            DWORD imageBase);
-    static std::vector<TString> GetImportsSection(DWORD base,
-            PIMAGE_NT_HEADERS pNTHeader);
-    static std::vector<TString> DumpPEFile(PIMAGE_DOS_HEADER dosHeader);
-
-public:
-    WindowsLibrary(const TString FileName);
-
-    std::vector<TString> GetImports();
-};
-
-
-class WindowsJob {
-private:
-    HANDLE FHandle;
-
-public:
-    WindowsJob();
-    ~WindowsJob();
-
-    HANDLE GetHandle();
-};
-
-
-class WindowsProcess : public Process {
-private:
-    bool FRunning;
-
-    PROCESS_INFORMATION FProcessInfo;
-    static WindowsJob FJob;
-
-    void Cleanup();
-    bool ReadOutput();
-
-public:
-    WindowsProcess();
-    virtual ~WindowsProcess();
-
-    virtual bool IsRunning();
-    virtual bool Terminate();
-    virtual bool Execute(const TString Application,
-            const std::vector<TString> Arguments, bool AWait = false);
-    virtual bool Wait();
-    virtual TProcessID GetProcessID();
-    virtual void SetInput(TString Value);
-    virtual std::list<TString> GetOutput();
-};
-
-#endif // WINDOWSPLATFORM_H
--- a/src/jdk.jpackage/windows/native/libjpackage/ByteBuffer.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.
- */
-
-#include "ByteBuffer.h"
-
-#include <stdio.h>
-
-ByteBuffer::ByteBuffer() {
-    buffer.reserve(1024);
-}
-
-ByteBuffer::~ByteBuffer() {
-}
-
-LPBYTE ByteBuffer::getPtr() {
-    return &buffer[0];
-}
-
-size_t ByteBuffer::getPos() {
-    return buffer.size();
-}
-
-void ByteBuffer::AppendString(wstring str) {
-    size_t len = (str.size() + 1) * sizeof (WCHAR);
-    AppendBytes((BYTE*) str.c_str(), len);
-}
-
-void ByteBuffer::AppendWORD(WORD word) {
-    AppendBytes((BYTE*) & word, sizeof (WORD));
-}
-
-void ByteBuffer::Align(size_t bytesNumber) {
-    size_t pos = getPos();
-    if (pos % bytesNumber) {
-        DWORD dwNull = 0;
-        size_t len = bytesNumber - pos % bytesNumber;
-        AppendBytes((BYTE*) & dwNull, len);
-    }
-}
-
-void ByteBuffer::AppendBytes(BYTE* ptr, size_t len) {
-    buffer.insert(buffer.end(), ptr, ptr + len);
-}
-
-void ByteBuffer::ReplaceWORD(size_t offset, WORD word) {
-    ReplaceBytes(offset, (BYTE*) & word, sizeof (WORD));
-}
-
-void ByteBuffer::ReplaceBytes(size_t offset, BYTE* ptr, size_t len) {
-    for (size_t i = 0; i < len; i++) {
-        buffer[offset + i] = *(ptr + i);
-    }
-}
--- a/src/jdk.jpackage/windows/native/libjpackage/ByteBuffer.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.
- */
-
-#ifndef BYTEBUFFER_H
-#define BYTEBUFFER_H
-
-#include <windows.h>
-#include <vector>
-#include <string>
-
-using namespace std;
-
-class ByteBuffer {
-public:
-    ByteBuffer();
-    ~ByteBuffer();
-
-    LPBYTE getPtr();
-    size_t getPos();
-
-    void AppendString(wstring str);
-    void AppendWORD(WORD word);
-    void AppendBytes(BYTE* ptr, size_t len);
-
-    void ReplaceWORD(size_t offset, WORD word);
-    void ReplaceBytes(size_t offset, BYTE* ptr, size_t len);
-
-    void Align(size_t bytesNumber);
-
-private:
-    vector<BYTE> buffer;
-};
-
-#endif // BYTEBUFFER_H
\ No newline at end of file
--- a/src/jdk.jpackage/windows/native/libjpackage/ErrorHandling.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include <algorithm>
-
-#include "ErrorHandling.h"
-#include "Log.h"
-
-
-namespace {
-
-tstring getFilename(const SourceCodePos& pos) {
-    const std::string buf(pos.file);
-    const std::string::size_type idx = buf.find_last_of("\\/");
-    if (idx == std::string::npos) {
-        return tstrings::fromUtf8(buf);
-    }
-    return tstrings::fromUtf8(buf.substr(idx + 1));
-}
-
-void reportError(const SourceCodePos& pos, const tstring& msg) {
-    Logger::defaultLogger().log(Logger::LOG_ERROR, getFilename(pos).c_str(),
-        pos.lno, tstrings::fromUtf8(pos.func).c_str(), msg);
-}
-
-} // namespace
-
-void reportError(const SourceCodePos& pos, const std::exception& e) {
-    reportError(pos, (tstrings::any() << "Exception with message \'"
-                                        << e.what() << "\' caught").tstr());
-}
-
-
-void reportUnknownError(const SourceCodePos& pos) {
-    reportError(pos, _T("Unknown exception caught"));
-}
-
-
-std::string makeMessage(const std::exception& e, const SourceCodePos& pos) {
-    std::ostringstream printer;
-    printer << getFilename(pos) << "(" << pos.lno << ") at "
-            << pos.func << "(): "
-            << e.what();
-    return printer.str();
-}
-
-
-namespace {
-
-bool isNotSpace(int chr) {
-    return isspace(chr) == 0;
-}
-
-
-enum TrimMode {
-    TrimLeading = 0x10,
-    TrimTrailing = 0x20,
-    TrimBoth = TrimLeading | TrimTrailing
-};
-
-// Returns position of the last printed character in the given string.
-// Returns std::string::npos if nothing was printed.
-size_t printWithoutWhitespaces(std::ostream& out, const std::string& str,
-                                                            TrimMode mode) {
-    std::string::const_reverse_iterator it = str.rbegin();
-    std::string::const_reverse_iterator end = str.rend();
-
-    if (mode & TrimLeading) {
-        // skip leading whitespace
-        std::string::const_iterator entry = std::find_if(str.begin(),
-                                                str.end(), isNotSpace);
-        end = std::string::const_reverse_iterator(entry);
-    }
-
-    if (mode & TrimTrailing) {
-        // skip trailing whitespace
-        it = std::find_if(it, end, isNotSpace);
-    }
-
-    if (it == end) {
-        return std::string::npos;
-    }
-
-    const size_t pos = str.rend() - end;
-    const size_t len = end - it;
-    out.write(str.c_str() + pos, len);
-    return pos + len - 1;
-}
-
-} // namespace
-
-std::string joinErrorMessages(const std::string& a, const std::string& b) {
-    const std::string endPhraseChars(";.,:!?");
-    const std::string space(" ");
-    const std::string dotAndSpace(". ");
-
-    std::ostringstream printer;
-    printer.exceptions(std::ios::failbit | std::ios::badbit);
-
-    size_t idx = printWithoutWhitespaces(printer, a, TrimTrailing);
-    size_t extra = 0;
-    if (idx < a.size() && endPhraseChars.find(a[idx]) == std::string::npos) {
-        printer << dotAndSpace;
-        extra = dotAndSpace.size();
-    } else if (idx != std::string::npos) {
-        printer << space;
-        extra = space.size();
-    }
-
-    idx = printWithoutWhitespaces(printer, b, TrimBoth);
-
-    const std::string str = printer.str();
-
-    if (std::string::npos == idx && extra) {
-        // Nothing printed from the 'b' message. Backout delimiter string.
-        return str.substr(0, str.size() - extra);
-    }
-    return str;
-}
--- a/src/jdk.jpackage/windows/native/libjpackage/ErrorHandling.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef ErrorHandling_h
-#define ErrorHandling_h
-
-
-#include <stdexcept>
-
-#include "SourceCodePos.h"
-#include "tstrings.h"
-
-
-//
-// Exception handling helpers. Allow transparent exception logging.
-// Use as follows:
-//
-//  void foo () {
-//      JP_TRY;
-//
-//      if (!do_something()) {
-//          JP_THROW("do_something() failed");
-//      }
-//
-//      JP_CATCH_ALL;
-//  }
-//
-
-
-// Logs std::exception caught at 'pos'.
-void reportError(const SourceCodePos& pos, const std::exception& e);
-// Logs unknown exception caught at 'pos'.
-// Assumed to be called from catch (...) {}
-void reportUnknownError(const SourceCodePos& pos);
-
-std::string makeMessage(const std::exception& e, const SourceCodePos& pos);
-
-std::string joinErrorMessages(const std::string& a, const std::string& b);
-
-
-template <class Base>
-class JpError: public Base {
-public:
-    JpError(const Base& e, const SourceCodePos& pos):
-                                        Base(e), msg(::makeMessage(e, pos)) {
-    }
-
-    ~JpError() throw() {
-    }
-
-    // override Base::what()
-    const char* what() const throw() {
-        return msg.c_str();
-    }
-private:
-    // Assert Base is derived from std::exception
-    enum { isDerivedFromStdException =
-                        sizeof(static_cast<std::exception*>((Base*)0)) };
-
-    std::string msg;
-};
-
-template <class T>
-inline JpError<T> makeException(const T& obj, const SourceCodePos& p) {
-    return JpError<T>(obj, p);
-}
-
-inline JpError<std::runtime_error> makeException(
-                            const std::string& msg, const SourceCodePos& p) {
-    return JpError<std::runtime_error>(std::runtime_error(msg), p);
-}
-
-inline JpError<std::runtime_error> makeException(
-                        const tstrings::any& msg, const SourceCodePos& p) {
-    return makeException(msg.str(), p);
-}
-
-inline JpError<std::runtime_error> makeException(
-                    std::string::const_pointer msg, const SourceCodePos& p) {
-    return makeException(std::string(msg), p);
-}
-
-
-#define JP_REPORT_ERROR(e)          reportError(JP_SOURCE_CODE_POS, e)
-#define JP_REPORT_UNKNOWN_ERROR     reportUnknownError(JP_SOURCE_CODE_POS)
-
-// Redefine locally in cpp file(s) if need more handling than just reporting
-#define JP_HANDLE_ERROR(e)          JP_REPORT_ERROR(e)
-#define JP_HANDLE_UNKNOWN_ERROR     JP_REPORT_UNKNOWN_ERROR
-
-
-#define JP_TRY                              \
-        try                                 \
-        {                                   \
-            do {} while(0)
-
-#define JP_DEFAULT_CATCH_EXCEPTIONS         \
-        JP_CATCH_STD_EXCEPTION              \
-        JP_CATCH_UNKNOWN_EXCEPTION
-
-#define JP_CATCH_EXCEPTIONS                 \
-        JP_DEFAULT_CATCH_EXCEPTIONS
-
-#define JP_CATCH_ALL                        \
-        }                                   \
-        JP_CATCH_EXCEPTIONS                 \
-        do {} while(0)
-
-#define JP_CATCH_STD_EXCEPTION              \
-        catch (const std::exception& e)     \
-        {                                   \
-            JP_HANDLE_ERROR(e);             \
-        }
-
-#define JP_CATCH_UNKNOWN_EXCEPTION          \
-        catch (...)                         \
-        {                                   \
-            JP_HANDLE_UNKNOWN_ERROR;        \
-        }
-
-
-#define JP_THROW(e) throw makeException((e), JP_SOURCE_CODE_POS)
-
-#define JP_NO_THROW(expr) \
-    JP_TRY; \
-    expr; \
-    JP_CATCH_ALL
-
-#endif // #ifndef ErrorHandling_h
--- a/src/jdk.jpackage/windows/native/libjpackage/FileUtils.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,709 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include <memory>
-#include <algorithm>
-#include <shlwapi.h>
-
-#include "FileUtils.h"
-#include "WinErrorHandling.h"
-#include "Log.h"
-
-
-// Needed by FileUtils::isDirectoryNotEmpty
-#pragma comment(lib, "shlwapi")
-
-
-namespace FileUtils {
-
-namespace {
-
-
-tstring reservedFilenameChars() {
-    tstring buf;
-    for (char charCode = 0; charCode < 32; ++charCode) {
-        buf.append(1, charCode);
-    }
-    buf += _T("<>:\"|?*/\\");
-    return buf;
-}
-
-} // namespace
-
-bool isDirSeparator(const tstring::value_type c) {
-    return (c == '/' || c == '\\');
-}
-
-bool isFileExists(const tstring &filePath) {
-    return GetFileAttributes(filePath.c_str()) != INVALID_FILE_ATTRIBUTES;
-}
-
-namespace {
-bool isDirectoryAttrs(const DWORD attrs) {
-    return attrs != INVALID_FILE_ATTRIBUTES
-            && (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
-}
-} // namespace
-
-bool isDirectory(const tstring &filePath) {
-    return isDirectoryAttrs(GetFileAttributes(filePath.c_str()));
-}
-
-bool isDirectoryNotEmpty(const tstring &dirPath) {
-    if (!isDirectory(dirPath)) {
-        return false;
-    }
-    return FALSE == PathIsDirectoryEmpty(dirPath.c_str());
-}
-
-tstring dirname(const tstring &path) {
-    tstring::size_type pos = path.find_last_of(_T("\\/"));
-    if (pos != tstring::npos) {
-        pos = path.find_last_not_of(_T("\\/"), pos); // skip trailing slashes
-    }
-    return pos == tstring::npos ? tstring() : path.substr(0, pos + 1);
-}
-
-tstring basename(const tstring &path) {
-    const tstring::size_type pos = path.find_last_of(_T("\\/"));
-    if (pos == tstring::npos) {
-        return path;
-    }
-    return path.substr(pos + 1);
-}
-
-tstring suffix(const tstring &path) {
-    const tstring::size_type pos = path.rfind('.');
-    if (pos == tstring::npos) {
-        return tstring();
-    }
-    const tstring::size_type dirSepPos = path.find_first_of(_T("\\/"),
-                                                            pos + 1);
-    if (dirSepPos != tstring::npos) {
-        return tstring();
-    }
-    // test for '/..' and '..' cases
-    if (pos != 0 && path[pos - 1] == '.'
-                            && (pos == 1 || isDirSeparator(path[pos - 2]))) {
-        return tstring();
-    }
-    return path.substr(pos);
-}
-
-tstring combinePath(const tstring& parent, const tstring& child) {
-    if (parent.empty()) {
-        return child;
-    }
-    if (child.empty()) {
-        return parent;
-    }
-
-    tstring parentWOSlash = removeTrailingSlash(parent);
-    // also handle the case when child contains starting slash
-    bool childHasSlash = isDirSeparator(child.front());
-    tstring childWOSlash = childHasSlash ? child.substr(1) : child;
-
-    return parentWOSlash + _T("\\") + childWOSlash;
-}
-
-tstring removeTrailingSlash(const tstring& path) {
-    if (path.empty()) {
-        return path;
-    }
-    tstring::const_reverse_iterator it = path.rbegin();
-    tstring::const_reverse_iterator end = path.rend();
-
-    while (it != end && isDirSeparator(*it)) {
-        ++it;
-    }
-    return path.substr(0, end - it);
-}
-
-tstring normalizePath(tstring v) {
-    std::replace(v.begin(), v.end(), '/', '\\');
-    return tstrings::toLower(v);
-}
-
-namespace {
-
-bool createNewFile(const tstring& path) {
-    HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
-            FILE_ATTRIBUTE_NORMAL, NULL);
-    // if the file exists => h == INVALID_HANDLE_VALUE & GetLastError
-    // returns ERROR_FILE_EXISTS
-    if (h != INVALID_HANDLE_VALUE) {
-        CloseHandle(h);
-        LOG_TRACE(tstrings::any() << "Created [" << path << "] file");
-        return true;
-    }
-    return false;
-}
-
-} // namespace
-
-tstring createTempFile(const tstring &prefix, const tstring &suffix,
-        const tstring &path) {
-    const tstring invalidChars = reservedFilenameChars();
-
-    if (prefix.find_first_of(invalidChars) != tstring::npos) {
-        JP_THROW(tstrings::any() << "Illegal characters in prefix=" << prefix);
-    }
-
-    if (suffix.find_first_of(invalidChars) != tstring::npos) {
-        JP_THROW(tstrings::any() << "Illegal characters in suffix=" << suffix);
-    }
-
-    int rnd = (int)GetTickCount();
-
-    // do no more than 100 attempts
-    for (int i=0; i<100; i++) {
-        const tstring filePath = mkpath() << path << (prefix
-                + (tstrings::any() << (rnd + i)).tstr() + suffix);
-        if (createNewFile(filePath)) {
-            return filePath;
-        }
-    }
-
-    // 100 attempts failed
-    JP_THROW(tstrings::any() << "createTempFile("  << prefix << ", "
-                                                    << suffix << ", "
-                                                    << path << ") failed");
-}
-
-tstring createTempDirectory(const tstring &prefix, const tstring &suffix,
-        const tstring &basedir) {
-    const tstring filePath = createTempFile(prefix, suffix, basedir);
-    // delete the file and create directory with the same name
-    deleteFile(filePath);
-    createDirectory(filePath);
-    return filePath;
-}
-
-tstring createUniqueFile(const tstring &prototype) {
-    if (createNewFile(prototype)) {
-        return prototype;
-    }
-
-    return createTempFile(replaceSuffix(basename(prototype)),
-            suffix(prototype), dirname(prototype));
-}
-
-namespace {
-
-void createDir(const tstring path, LPSECURITY_ATTRIBUTES saAttr,
-        tstring_array* createdDirs=0) {
-    if (CreateDirectory(path.c_str(), saAttr)) {
-        LOG_TRACE(tstrings::any() << "Created [" << path << "] directory");
-        if (createdDirs) {
-            createdDirs->push_back(removeTrailingSlash(path));
-        }
-    } else {
-        const DWORD createDirectoryErr = GetLastError();
-        // if saAttr is specified, fail even if the directory exists
-        if (saAttr != NULL || !isDirectory(path)) {
-            JP_THROW(SysError(tstrings::any() << "CreateDirectory("
-                << path << ") failed", CreateDirectory, createDirectoryErr));
-        }
-    }
-}
-
-}
-
-void createDirectory(const tstring &path, tstring_array* createdDirs) {
-    const tstring dirPath = removeTrailingSlash(path) + _T("\\");
-
-    tstring::size_type pos = dirPath.find_first_of(_T("\\/"));
-    while (pos != tstring::npos) {
-        const tstring subdirPath = dirPath.substr(0, pos + 1);
-        createDir(subdirPath, NULL, createdDirs);
-        pos = dirPath.find_first_of(_T("\\/"), pos + 1);
-    }
-}
-
-
-void copyFile(const tstring& fromPath, const tstring& toPath,
-        bool failIfExists) {
-    createDirectory(dirname(toPath));
-    if (!CopyFile(fromPath.c_str(), toPath.c_str(),
-            (failIfExists ? TRUE : FALSE))) {
-        JP_THROW(SysError(tstrings::any()
-                << "CopyFile(" << fromPath << ", " << toPath << ", "
-                << failIfExists << ") failed", CopyFile));
-    }
-    LOG_TRACE(tstrings::any() << "Copied [" << fromPath << "] file to ["
-            << toPath << "]");
-}
-
-
-namespace {
-
-void moveFileImpl(const tstring& fromPath, const tstring& toPath,
-        DWORD flags) {
-    const bool isDir = isDirectory(fromPath);
-    if (!MoveFileEx(fromPath.c_str(), toPath.empty() ? NULL : toPath.c_str(),
-            flags)) {
-        JP_THROW(SysError(tstrings::any() << "MoveFileEx(" << fromPath
-                << ", " << toPath << ", " << flags << ") failed", MoveFileEx));
-    }
-
-    const bool onReboot = 0 != (flags & MOVEFILE_DELAY_UNTIL_REBOOT);
-
-    const LPCTSTR label = isDir ? _T("folder") : _T("file");
-
-    tstrings::any msg;
-    if (!toPath.empty()) {
-        if (onReboot) {
-            msg << "Move";
-        } else {
-            msg << "Moved";
-        }
-        msg << " '" << fromPath << "' " << label << " to '" << toPath << "'";
-    } else {
-        if (onReboot) {
-            msg << "Delete";
-        } else {
-            msg << "Deleted";
-        }
-        msg << " '" << fromPath << "' " << label;
-    }
-    if (onReboot) {
-        msg << " on reboot";
-    }
-    LOG_TRACE(msg);
-}
-
-} // namespace
-
-
-void moveFile(const tstring& fromPath, const tstring& toPath,
-        bool failIfExists) {
-    createDirectory(dirname(toPath));
-
-    DWORD flags = MOVEFILE_COPY_ALLOWED;
-    if (!failIfExists) {
-        flags |= MOVEFILE_REPLACE_EXISTING;
-    }
-
-    moveFileImpl(fromPath, toPath, flags);
-}
-
-void deleteFile(const tstring &path)
-{
-    if (!deleteFile(path, std::nothrow)) {
-        JP_THROW(SysError(tstrings::any()
-                << "DeleteFile(" << path << ") failed", DeleteFile));
-    }
-}
-
-namespace {
-
-bool notFound(const DWORD status=GetLastError()) {
-    return status == ERROR_FILE_NOT_FOUND || status == ERROR_PATH_NOT_FOUND;
-}
-
-bool deleteFileImpl(const std::nothrow_t &, const tstring &path) {
-    const bool deleted = (DeleteFile(path.c_str()) != 0);
-    if (deleted) {
-        LOG_TRACE(tstrings::any() << "Deleted [" << path << "] file");
-        return true;
-    }
-    return notFound();
-}
-
-} // namespace
-
-bool deleteFile(const tstring &path, const std::nothrow_t &) throw()
-{
-    bool deleted = deleteFileImpl(std::nothrow, path);
-    const DWORD status = GetLastError();
-    if (!deleted && status == ERROR_ACCESS_DENIED) {
-        DWORD attrs = GetFileAttributes(path.c_str());
-        SetLastError(status);
-        if (attrs == INVALID_FILE_ATTRIBUTES) {
-            return false;
-        }
-        if (attrs & FILE_ATTRIBUTE_READONLY) {
-            // DeleteFile() failed because file is R/O.
-            // Remove R/O attribute and retry DeleteFile().
-            attrs &= ~FILE_ATTRIBUTE_READONLY;
-            if (SetFileAttributes(path.c_str(), attrs)) {
-                LOG_TRACE(tstrings::any() << "Discarded R/O attribute from ["
-                                                        << path << "] file");
-                deleted = deleteFileImpl(std::nothrow, path);
-            } else {
-                LOG_WARNING(SysError(tstrings::any()
-                            << "Failed to discard R/O attribute from ["
-                            << path << "] file. File will not be deleted",
-                            SetFileAttributes).what());
-                SetLastError(status);
-            }
-        }
-    }
-
-    return deleted || notFound();
-}
-
-void deleteDirectory(const tstring &path)
-{
-    if (!deleteDirectory(path, std::nothrow)) {
-        JP_THROW(SysError(tstrings::any()
-                << "RemoveDirectory(" << path << ") failed", RemoveDirectory));
-    }
-}
-
-bool deleteDirectory(const tstring &path, const std::nothrow_t &) throw()
-{
-    const bool deleted = (RemoveDirectory(path.c_str()) != 0);
-    if (deleted) {
-        LOG_TRACE(tstrings::any() << "Deleted [" << path << "] directory");
-    }
-    return deleted || notFound();
-}
-
-namespace {
-
-class DeleteFilesCallback: public DirectoryCallback {
-public:
-    explicit DeleteFilesCallback(bool ff): failfast(ff), failed(false) {
-    }
-
-    virtual bool onFile(const tstring& path) {
-        if (failfast) {
-            deleteFile(path);
-        } else {
-            updateStatus(deleteFile(path, std::nothrow));
-        }
-        return true;
-    }
-
-    bool good() const {
-        return !failed;
-    }
-
-protected:
-    void updateStatus(bool success) {
-        if (!success) {
-            failed = true;
-        }
-    }
-
-    const bool failfast;
-private:
-    bool failed;
-};
-
-class DeleteAllCallback: public DeleteFilesCallback {
-public:
-    explicit DeleteAllCallback(bool failfast): DeleteFilesCallback(failfast) {
-    }
-
-    virtual bool onDirectory(const tstring& path) {
-        if (failfast) {
-            deleteDirectoryRecursive(path);
-        } else {
-            updateStatus(deleteDirectoryRecursive(path, std::nothrow));
-        }
-        return true;
-    }
-};
-
-
-class BatchDeleter {
-    const tstring dirPath;
-    bool recursive;
-public:
-    explicit BatchDeleter(const tstring& path): dirPath(path) {
-        deleteSubdirs(false);
-    }
-
-    BatchDeleter& deleteSubdirs(bool v) {
-        recursive = v;
-        return *this;
-    }
-
-    void execute() const {
-        if (!isFileExists(dirPath)) {
-            return;
-        }
-        iterateDirectory(true /* fail fast */);
-        if (recursive) {
-            deleteDirectory(dirPath);
-        }
-    }
-
-    bool execute(const std::nothrow_t&) const {
-        if (!isFileExists(dirPath)) {
-            return true;
-        }
-
-        if (!isDirectory(dirPath)) {
-            return false;
-        }
-
-        JP_TRY;
-        if (!iterateDirectory(false /* ignore errors */)) {
-            return false;
-        }
-        if (recursive) {
-            return deleteDirectory(dirPath, std::nothrow);
-        }
-        return true;
-        JP_CATCH_ALL;
-
-        return false;
-    }
-
-private:
-    bool iterateDirectory(bool failfast) const {
-        std::unique_ptr<DeleteFilesCallback> callback;
-        if (recursive) {
-            callback = std::unique_ptr<DeleteFilesCallback>(
-                                            new DeleteAllCallback(failfast));
-        } else {
-            callback = std::unique_ptr<DeleteFilesCallback>(
-                                            new DeleteFilesCallback(failfast));
-        }
-
-        FileUtils::iterateDirectory(dirPath, *callback);
-        return callback->good();
-    }
-};
-
-} // namespace
-
-void deleteFilesInDirectory(const tstring &dirPath) {
-    BatchDeleter(dirPath).execute();
-}
-
-bool deleteFilesInDirectory(const tstring &dirPath,
-                                            const std::nothrow_t &) throw() {
-    return BatchDeleter(dirPath).execute(std::nothrow);
-}
-
-void deleteDirectoryRecursive(const tstring &dirPath) {
-    BatchDeleter(dirPath).deleteSubdirs(true).execute();
-}
-
-bool deleteDirectoryRecursive(const tstring &dirPath,
-                                            const std::nothrow_t &) throw() {
-    return BatchDeleter(dirPath).deleteSubdirs(true).execute(std::nothrow);
-}
-
-namespace {
-
-struct FindFileDeleter {
-    typedef HANDLE pointer;
-
-    void operator()(HANDLE h) {
-        if (h && h != INVALID_HANDLE_VALUE) {
-            FindClose(h);
-        }
-    }
-};
-
-typedef std::unique_ptr<HANDLE, FindFileDeleter> UniqueFindFileHandle;
-
-}; // namesace
-void iterateDirectory(const tstring &dirPath, DirectoryCallback& callback)
-{
-    const tstring searchString = combinePath(dirPath, _T("*"));
-    WIN32_FIND_DATA findData;
-    UniqueFindFileHandle h(FindFirstFile(searchString.c_str(), &findData));
-    if (h.get() == INVALID_HANDLE_VALUE) {
-        // GetLastError() == ERROR_FILE_NOT_FOUND is OK
-        // - no files in the directory
-        // ERROR_PATH_NOT_FOUND is returned
-        // if the parent directory does not exist
-        if (GetLastError() != ERROR_FILE_NOT_FOUND) {
-            JP_THROW(SysError(tstrings::any() << "FindFirstFile("
-                    << dirPath << ") failed", FindFirstFile));
-        }
-        return;
-    }
-
-    do {
-        const tstring fname(findData.cFileName);
-        const tstring filePath = combinePath(dirPath, fname);
-        if (!isDirectoryAttrs(findData.dwFileAttributes)) {
-            if (!callback.onFile(filePath)) {
-                return;
-            }
-        } else if (fname != _T(".") && fname != _T("..")) {
-            if (!callback.onDirectory(filePath)) {
-                return;
-            }
-        }
-    } while (FindNextFile(h.get(), &findData));
-
-    // expect GetLastError() == ERROR_NO_MORE_FILES
-    if (GetLastError() != ERROR_NO_MORE_FILES) {
-        JP_THROW(SysError(tstrings::any() << "FindNextFile("
-                << dirPath << ") failed", FindNextFile));
-    }
-}
-
-
-tstring replaceSuffix(const tstring& path, const tstring& newSuffix) {
-    return (path.substr(0, path.size() - suffix(path).size()) + newSuffix);
-}
-
-
-DirectoryIterator& DirectoryIterator::findItems(tstring_array& v) {
-    if (!isDirectory(root)) {
-        return *this;
-    }
-
-    iterateDirectory(root, *this);
-    v.insert(v.end(), items.begin(), items.end());
-    items = tstring_array();
-    return *this;
-}
-
-bool DirectoryIterator::onFile(const tstring& path) {
-    if (theWithFiles) {
-        items.push_back(path);
-    }
-    return true;
-}
-
-bool DirectoryIterator::onDirectory(const tstring& path) {
-    if (theWithFolders) {
-        items.push_back(path);
-    }
-    if (theRecurse) {
-        DirectoryIterator(path).recurse(theRecurse)
-                .withFiles(theWithFiles)
-                .withFolders(theWithFolders)
-                .findItems(items);
-    }
-    return true;
-}
-
-
-namespace {
-
-struct DeleterFunctor {
-    // Order of items in the following enum is important!
-    // It controls order in which items of particular type will be deleted.
-    // See Deleter::execute().
-    enum {
-        File,
-        FilesInDirectory,
-        RecursiveDirectory,
-        EmptyDirectory
-    };
-
-    void operator () (const Deleter::Path& path) const {
-        switch (path.second) {
-#define DELETE_SOME(o, f)\
-        case o:\
-            f(path.first, std::nothrow);\
-            break
-
-        DELETE_SOME(File, deleteFile);
-        DELETE_SOME(EmptyDirectory, deleteDirectory);
-        DELETE_SOME(FilesInDirectory, deleteFilesInDirectory);
-        DELETE_SOME(RecursiveDirectory, deleteDirectoryRecursive);
-
-#undef DELETE_SOME
-        default:
-            break;
-        }
-    }
-};
-
-} // namespace
-
-void Deleter::execute() {
-    Paths tmp;
-    tmp.swap(paths);
-
-    // Reorder items to delete.
-    std::stable_sort(tmp.begin(), tmp.end(), [] (const Paths::value_type& a,
-                                                const Paths::value_type& b) {
-        return a.second < b.second;
-    });
-
-    std::for_each(tmp.begin(), tmp.end(), DeleterFunctor());
-}
-
-Deleter& Deleter::appendFile(const tstring& path) {
-    paths.push_back(std::make_pair(path, DeleterFunctor::File));
-    return *this;
-}
-
-Deleter& Deleter::appendEmptyDirectory(const Directory& dir) {
-     tstring path =  normalizePath(removeTrailingSlash(dir));
-     const tstring parent = normalizePath(removeTrailingSlash(dir.parent));
-     while(parent != path) {
-         appendEmptyDirectory(path);
-         path = dirname(path);
-     }
-
-    return *this;
-}
-
-Deleter& Deleter::appendEmptyDirectory(const tstring& path) {
-    paths.push_back(std::make_pair(path, DeleterFunctor::EmptyDirectory));
-    return *this;
-}
-
-Deleter& Deleter::appendAllFilesInDirectory(const tstring& path) {
-    paths.push_back(std::make_pair(path, DeleterFunctor::FilesInDirectory));
-    return *this;
-}
-
-Deleter& Deleter::appendRecursiveDirectory(const tstring& path) {
-    paths.push_back(std::make_pair(path, DeleterFunctor::RecursiveDirectory));
-    return *this;
-}
-
-
-FileWriter::FileWriter(const tstring& path): dstPath(path) {
-    tmpFile = FileUtils::createTempFile(_T("jds"), _T(".tmp"),
-            FileUtils::dirname(path));
-
-    cleaner.appendFile(tmpFile);
-
-    // we want to get exception on error
-    tmp.exceptions(std::ifstream::failbit | std::ifstream::badbit);
-    tmp.open(tmpFile, std::ios::binary | std::ios::trunc);
-}
-
-FileWriter& FileWriter::write(const void* buf, size_t bytes) {
-    tmp.write(static_cast<const char*>(buf), bytes);
-    return *this;
-}
-
-void FileWriter::finalize() {
-    tmp.close();
-
-    FileUtils::moveFile(tmpFile, dstPath, false);
-
-    // cancel file deletion
-    cleaner.cancel();
-}
-
-} //  namespace FileUtils
--- a/src/jdk.jpackage/windows/native/libjpackage/FileUtils.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,398 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef FILEUTILS_H
-#define FILEUTILS_H
-
-
-#include <fstream>
-#include "SysInfo.h"
-
-
-namespace FileUtils {
-
-    // Returns 'true' if the given character is a path separator.
-    bool isDirSeparator(const tstring::value_type c);
-
-    // checks if the file or directory exists
-    bool isFileExists(const tstring &filePath);
-
-    // checks is the specified file is a directory
-    // returns false if the path does not exist
-    bool isDirectory(const tstring &filePath);
-
-    // checks if the specified directory is not empty
-    // returns true if the path is an existing directory and
-    // it contains at least one file other than "." or "..".
-    bool isDirectoryNotEmpty(const tstring &dirPath);
-
-    // returns directory part of the path.
-    // returns empty string if the path contains only filename.
-    // if the path ends with slash/backslash,
-    // returns removeTrailingSlashes(path).
-    tstring dirname(const tstring &path);
-
-    // returns basename part of the path
-    // if the path ends with slash/backslash, returns empty string.
-    tstring basename(const tstring &path);
-
-    /**
-     * Translates forward slashes to back slashes and returns lower case version
-     * of the given string.
-     */
-    tstring normalizePath(tstring v);
-
-    // Returns suffix of the path. If the given path has a suffix the first
-    // character of the return value is '.'.
-    // Otherwise return value if empty string.
-    tstring suffix(const tstring &path);
-
-    // combines two strings into a path
-    tstring combinePath(const tstring& parent, const tstring& child);
-
-    // removes trailing slashes and backslashes in the path if any
-    tstring removeTrailingSlash(const tstring& path);
-
-    // Creates a file with unique name in the specified base directory,
-    // throws an exception if operation fails
-    // path is constructed as <prefix><random number><suffix>.
-    // The function fails and throws exception if 'path' doesn't exist.
-    tstring createTempFile(const tstring &prefix = _T(""),
-            const tstring &suffix = _T(".tmp"),
-            const tstring &path=SysInfo::getTempDir());
-
-    // Creates a directory with unique name in the specified base directory,
-    // throws an exception if operation fails
-    // path is constructed as <prefix><random number><suffix>
-    // The function fails and throws exception if 'path' doesn't exist.
-    tstring createTempDirectory(const tstring &prefix = _T(""),
-            const tstring &suffix = _T(".tmp"),
-            const tstring &basedir=SysInfo::getTempDir());
-
-    // If the file referenced with "prototype" parameter DOES NOT exist,
-    // the return value is the given path. No new files created.
-    // Otherwise the function creates another file in the same directory as
-    // the given file with the same suffix and with the basename from the
-    // basename of the given file with some random chars appended to ensure
-    // created file is unique.
-    tstring createUniqueFile(const tstring &prototype);
-
-    // Creates directory and subdirectories if don't exist.
-    // Currently supports only "standard" path like "c:\bla-bla"
-    // If 'createdDirs' parameter is not NULL, the given array is appended with
-    // all subdirectories created by this function call.
-    void createDirectory(const tstring &path, tstring_array* createdDirs=0);
-
-    // copies file from fromPath to toPath.
-    // Creates output directory if doesn't exist.
-    void copyFile(const tstring& fromPath, const tstring& toPath,
-            bool failIfExists);
-
-    // moves file from fromPath to toPath.
-    // Creates output directory if doesn't exist.
-    void moveFile(const tstring& fromPath, const tstring& toPath,
-            bool failIfExists);
-
-    // Throws exception if fails to delete specified 'path'.
-    // Exits normally if 'path' doesn't exist or it has been deleted.
-    // Attempts to strip R/O attribute if delete fails and retry delete.
-    void deleteFile(const tstring &path);
-    // Returns 'false' if fails to delete specified 'path'.
-    // Returns 'true' if 'path' doesn't exist or it has been deleted.
-    // Attempts to strip R/O attribute if delete fails and retry delete.
-    bool deleteFile(const tstring &path, const std::nothrow_t &) throw();
-
-    // Like deleteFile(), but applies to directories.
-    void deleteDirectory(const tstring &path);
-    bool deleteDirectory(const tstring &path, const std::nothrow_t &) throw();
-
-    // Deletes all files (not subdirectories) from the specified directory.
-    // Exits normally if all files in 'dirPath' have been deleted or if
-    // 'dirPath' doesn't exist.
-    // Throws exception if 'dirPath' references existing file system object
-    // which is not a directory or when the first failure of file delete
-    // occurs.
-    void deleteFilesInDirectory(const tstring &dirPath);
-    // Deletes all files (not subdirectories) from the specified directory.
-    // Returns 'true' normally if all files in 'dirPath' have been deleted or
-    // if 'dirPath' doesn't exist.
-    // Returns 'false' if 'dirPath' references existing file system object
-    // which is not a directory or if failed to delete one ore more files in
-    // 'dirPath' directory.
-    // Doesn't abort iteration over files if the given directory after the
-    // first failure to delete a file.
-    bool deleteFilesInDirectory(const tstring &dirPath,
-            const std::nothrow_t &) throw();
-    // Like deleteFilesInDirectory, but deletes subdirectories as well
-    void deleteDirectoryRecursive(const tstring &dirPath);
-    bool deleteDirectoryRecursive(const tstring &dirPath,
-            const std::nothrow_t &) throw();
-
-    class DirectoryCallback {
-    public:
-        virtual ~DirectoryCallback() {};
-
-        virtual bool onFile(const tstring& path) {
-            return true;
-        }
-        virtual bool onDirectory(const tstring& path) {
-            return true;
-        }
-    };
-
-    // Calls the given callback for every file and subdirectory of
-    // the given directory.
-    void iterateDirectory(const tstring &dirPath, DirectoryCallback& callback);
-
-    /**
-     * Replace file suffix, example replaceSuffix("file/path.txt", ".csv")
-     * @param path file path to replace suffix
-     * @param suffix new suffix for path
-     * @return return file path with new suffix
-     */
-    tstring replaceSuffix(const tstring& path, const tstring& suffix=tstring());
-
-    class DirectoryIterator: DirectoryCallback {
-    public:
-        DirectoryIterator(const tstring& root=tstring()): root(root) {
-            recurse().withFiles().withFolders();
-        }
-
-        DirectoryIterator& recurse(bool v=true) {
-            theRecurse = v;
-            return *this;
-        }
-
-        DirectoryIterator& withFiles(bool v=true) {
-            theWithFiles = v;
-            return *this;
-        }
-
-        DirectoryIterator& withFolders(bool v=true) {
-            theWithFolders = v;
-            return *this;
-        }
-
-        tstring_array findItems() {
-            tstring_array reply;
-            findItems(reply);
-            return reply;
-        }
-
-        DirectoryIterator& findItems(tstring_array& v);
-
-    private:
-        virtual bool onFile(const tstring& path);
-        virtual bool onDirectory(const tstring& path);
-
-    private:
-        bool theRecurse;
-        bool theWithFiles;
-        bool theWithFolders;
-        tstring root;
-        tstring_array items;
-    };
-
-    // Returns array of all the files/sub-folders from the given directory,
-    // empty array if basedir is not a directory. The returned
-    // array is ordered from top down (i.e. dirs are listed first followed
-    // by subfolders and files).
-    // Order of subfolders and files is undefined
-    // but usually they are sorted by names.
-    inline tstring_array listAllContents(const tstring& basedir) {
-        return DirectoryIterator(basedir).findItems();
-    }
-
-    // Helper to construct path from multiple components.
-    //
-    // Sample usage:
-    //  Construct "c:\Program Files\Java" string from three components
-    //
-    //  tstring path = FileUtils::mkpath()  << _T("c:")
-    //                                      << _T("Program Files")
-    //                                      << _T("Java");
-    //
-    class mkpath {
-    public:
-        operator const tstring& () const {
-            return path;
-        }
-
-        mkpath& operator << (const tstring& p) {
-            path = combinePath(path, p);
-            return *this;
-        }
-
-        // mimic std::string
-        const tstring::value_type* c_str() const {
-            return path.c_str();
-        }
-    private:
-        tstring path;
-    };
-
-    struct Directory {
-        Directory() {
-        }
-
-        Directory(const tstring &parent,
-                const tstring &subdir) : parent(parent), subdir(subdir)  {
-        }
-
-        operator tstring () const {
-            return getPath();
-        }
-
-        tstring getPath() const {
-            return combinePath(parent, subdir);
-        }
-
-        bool empty() const {
-            return (parent.empty() && subdir.empty());
-        }
-
-        tstring parent;
-        tstring subdir;
-    };
-
-    // Deletes list of files and directories in batch mode.
-    // Registered files and directories are deleted when destructor is called.
-    // Order or delete operations is following:
-    //  - delete items registered with appendFile() calls;
-    //  - delete items registered with appendAllFilesInDirectory() calls;
-    //  - delete items registered with appendRecursiveDirectory() calls;
-    //  - delete items registered with appendEmptyDirectory() calls.
-    class Deleter {
-    public:
-        Deleter() {
-        }
-
-        ~Deleter() {
-            execute();
-        }
-
-        typedef std::pair<tstring, int> Path;
-        typedef std::vector<Path> Paths;
-
-        /**
-         * Appends all records from the given deleter Deleter into this Deleter
-         * instance. On success array with records in the passed in Deleter
-         * instance is emptied.
-         */
-        Deleter& appendFrom(Deleter& other) {
-            Paths tmp(paths);
-            tmp.insert(tmp.end(), other.paths.begin(), other.paths.end());
-            Paths empty;
-            other.paths.swap(empty);
-            paths.swap(tmp);
-            return *this;
-        }
-
-        // Schedule file for deletion.
-        Deleter& appendFile(const tstring& path);
-
-        // Schedule files for deletion.
-        template <class It>
-        Deleter& appendFiles(It b, It e) {
-            for (It it = b; it != e; ++it) {
-                appendFile(*it);
-            }
-            return *this;
-        }
-
-        // Schedule files for deletion in the given directory.
-        template <class It>
-        Deleter& appendFiles(const tstring& dirname, It b, It e) {
-            for (It it = b; it != e; ++it) {
-                appendFile(FileUtils::mkpath() << dirname << *it);
-            }
-            return *this;
-        }
-
-        // Schedule empty directory for deletion with empty roots
-        // (up to Directory.parent).
-        Deleter& appendEmptyDirectory(const Directory& dir);
-
-        // Schedule empty directory for deletion without roots.
-        // This is a particular case of
-        // appendEmptyDirectory(const Directory& dir)
-        // with Directory(dirname(path), basename(path)).
-        Deleter& appendEmptyDirectory(const tstring& path);
-
-        // Schedule all file from the given directory for deletion.
-        Deleter& appendAllFilesInDirectory(const tstring& path);
-
-        // Schedule directory for recursive deletion.
-        Deleter& appendRecursiveDirectory(const tstring& path);
-
-        void cancel() {
-            paths.clear();
-        }
-
-        // Deletes scheduled files and directories. After this function
-        // is called internal list of scheduled items is emptied.
-        void execute();
-
-    private:
-        Paths paths;
-    };
-
-
-    /**
-     * Helper to write chunks of data into binary file.
-     * Creates temporary file in the same folder with destination file.
-     * All subsequent requests to save data chunks are redirected to temporary
-     * file. finalize() method closes temporary file stream and renames
-     * temporary file.
-     * If finalize() method is not called, temporary file is deleted in
-     * ~FileWriter(), destination file is not touched.
-     */
-    class FileWriter {
-    public:
-        explicit FileWriter(const tstring& path);
-
-        FileWriter& write(const void* buf, size_t bytes);
-
-        template <class Ctnr>
-        FileWriter& write(const Ctnr& buf) {
-            return write(buf.data(),
-                            buf.size() * sizeof(typename Ctnr::value_type));
-        }
-
-        void finalize();
-
-    private:
-        // Not accessible by design!
-        FileWriter& write(const std::wstring& str);
-
-    private:
-        tstring tmpFile;
-        Deleter cleaner;
-        std::ofstream tmp;
-        tstring dstPath;
-    };
-} // FileUtils
-
-#endif // FILEUTILS_H
--- a/src/jdk.jpackage/windows/native/libjpackage/IconSwap.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2012, 2019, 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.
- */
-
-#include <stdio.h>
-#include <windows.h>
-#include <stdlib.h>
-#include <string>
-#include <malloc.h>
-
-using namespace std;
-
-// http://msdn.microsoft.com/en-us/library/ms997538.aspx
-
-typedef struct _ICONDIRENTRY {
-    BYTE bWidth;
-    BYTE bHeight;
-    BYTE bColorCount;
-    BYTE bReserved;
-    WORD wPlanes;
-    WORD wBitCount;
-    DWORD dwBytesInRes;
-    DWORD dwImageOffset;
-} ICONDIRENTRY, * LPICONDIRENTRY;
-
-typedef struct _ICONDIR {
-    WORD idReserved;
-    WORD idType;
-    WORD idCount;
-    ICONDIRENTRY idEntries[1];
-} ICONDIR, * LPICONDIR;
-
-// #pragmas are used here to insure that the structure's
-// packing in memory matches the packing of the EXE or DLL.
-#pragma pack(push)
-#pragma pack(2)
-
-typedef struct _GRPICONDIRENTRY {
-    BYTE bWidth;
-    BYTE bHeight;
-    BYTE bColorCount;
-    BYTE bReserved;
-    WORD wPlanes;
-    WORD wBitCount;
-    DWORD dwBytesInRes;
-    WORD nID;
-} GRPICONDIRENTRY, * LPGRPICONDIRENTRY;
-#pragma pack(pop)
-
-#pragma pack(push)
-#pragma pack(2)
-
-typedef struct _GRPICONDIR {
-    WORD idReserved;
-    WORD idType;
-    WORD idCount;
-    GRPICONDIRENTRY idEntries[1];
-} GRPICONDIR, * LPGRPICONDIR;
-#pragma pack(pop)
-
-void PrintError() {
-    LPVOID message = NULL;
-    DWORD error = GetLastError();
-
-    if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
-            | FORMAT_MESSAGE_FROM_SYSTEM
-            | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
-            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-            (LPTSTR) & message, 0, NULL) != 0) {
-        printf("%S", (LPTSTR) message);
-        LocalFree(message);
-    }
-}
-
-// Note: We do not check here that iconTarget is valid icon.
-// Java code will already do this for us.
-
-bool ChangeIcon(wstring iconTarget, wstring launcher) {
-    WORD language = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
-
-    HANDLE icon = CreateFile(iconTarget.c_str(), GENERIC_READ, 0, NULL,
-            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-    if (icon == INVALID_HANDLE_VALUE) {
-        PrintError();
-        return false;
-    }
-
-    // Reading .ICO file
-    WORD idReserved, idType, idCount;
-
-    DWORD dwBytesRead;
-    ReadFile(icon, &idReserved, sizeof (WORD), &dwBytesRead, NULL);
-    ReadFile(icon, &idType, sizeof (WORD), &dwBytesRead, NULL);
-    ReadFile(icon, &idCount, sizeof (WORD), &dwBytesRead, NULL);
-
-    LPICONDIR lpid = (LPICONDIR) malloc(
-            sizeof (ICONDIR) + (sizeof (ICONDIRENTRY) * (idCount - 1)));
-    if (lpid == NULL) {
-        CloseHandle(icon);
-        printf("Error: Failed to allocate memory\n");
-        return false;
-    }
-
-    lpid->idReserved = idReserved;
-    lpid->idType = idType;
-    lpid->idCount = idCount;
-
-    ReadFile(icon, &lpid->idEntries[0], sizeof (ICONDIRENTRY) * lpid->idCount,
-            &dwBytesRead, NULL);
-
-    LPGRPICONDIR lpgid = (LPGRPICONDIR) malloc(
-            sizeof (GRPICONDIR) + (sizeof (GRPICONDIRENTRY) * (idCount - 1)));
-    if (lpid == NULL) {
-        CloseHandle(icon);
-        free(lpid);
-        printf("Error: Failed to allocate memory\n");
-        return false;
-    }
-
-    lpgid->idReserved = idReserved;
-    lpgid->idType = idType;
-    lpgid->idCount = idCount;
-
-    for (int i = 0; i < lpgid->idCount; i++) {
-        lpgid->idEntries[i].bWidth = lpid->idEntries[i].bWidth;
-        lpgid->idEntries[i].bHeight = lpid->idEntries[i].bHeight;
-        lpgid->idEntries[i].bColorCount = lpid->idEntries[i].bColorCount;
-        lpgid->idEntries[i].bReserved = lpid->idEntries[i].bReserved;
-        lpgid->idEntries[i].wPlanes = lpid->idEntries[i].wPlanes;
-        lpgid->idEntries[i].wBitCount = lpid->idEntries[i].wBitCount;
-        lpgid->idEntries[i].dwBytesInRes = lpid->idEntries[i].dwBytesInRes;
-        lpgid->idEntries[i].nID = i + 1;
-    }
-
-    // Store images in .EXE
-    HANDLE update = BeginUpdateResource(launcher.c_str(), FALSE);
-    if (update == NULL) {
-        free(lpid);
-        free(lpgid);
-        CloseHandle(icon);
-        PrintError();
-        return false;
-    }
-
-    for (int i = 0; i < lpid->idCount; i++) {
-        LPBYTE lpBuffer = (LPBYTE) malloc(lpid->idEntries[i].dwBytesInRes);
-        SetFilePointer(icon, lpid->idEntries[i].dwImageOffset,
-                NULL, FILE_BEGIN);
-        ReadFile(icon, lpBuffer, lpid->idEntries[i].dwBytesInRes,
-                &dwBytesRead, NULL);
-        if (!UpdateResource(update, RT_ICON,
-                MAKEINTRESOURCE(lpgid->idEntries[i].nID),
-                language, &lpBuffer[0], lpid->idEntries[i].dwBytesInRes)) {
-            free(lpBuffer);
-            free(lpid);
-            free(lpgid);
-            CloseHandle(icon);
-            PrintError();
-            return false;
-        }
-        free(lpBuffer);
-    }
-
-    free(lpid);
-    CloseHandle(icon);
-
-    if (!UpdateResource(update, RT_GROUP_ICON, MAKEINTRESOURCE(1),
-            language, &lpgid[0], (sizeof (WORD) * 3)
-            + (sizeof (GRPICONDIRENTRY) * lpgid->idCount))) {
-        free(lpgid);
-        PrintError();
-        return false;
-    }
-
-    free(lpgid);
-
-    if (EndUpdateResource(update, FALSE) == FALSE) {
-        PrintError();
-        return false;
-    }
-
-    return true;
-}
--- a/src/jdk.jpackage/windows/native/libjpackage/IconSwap.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2016, 2019, 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.
- */
-
-#ifndef ICONSWAP_H
-#define ICONSWAP_H
-
-#include <string>
-
-using namespace std;
-
-bool ChangeIcon(wstring iconTarget, wstring launcher);
-
-#endif // ICONSWAP_H
\ No newline at end of file
--- a/src/jdk.jpackage/windows/native/libjpackage/Log.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include "Log.h"
-#include "SysInfo.h"
-#include "FileUtils.h"
-
-
-namespace {
-    //
-    // IMPORTANT: Static objects with non-trivial constructors are NOT allowed
-    // in logger module. Allocate buffers only and do lazy initialization of
-    // globals in Logger::getDefault().
-    //
-    // Logging subsystem is used almost in every module, and logging API can be
-    // called from constructors of static objects in various modules. As
-    // ordering of static objects initialization between modules is undefined,
-    // this means some module may call logging api before logging static
-    // variables are initialized if any. This will result in AV. To avoid such
-    // use cases keep logging module free from static variables that require
-    // initialization with functions called by CRT.
-    //
-
-    // by default log everything
-    const Logger::LogLevel defaultLogLevel = Logger::LOG_TRACE;
-
-    char defaultLogAppenderMemory[sizeof(StderrLogAppender)] = {};
-
-    char defaultLoggerMemory[sizeof(Logger)] = {};
-
-    NopLogAppender nopLogApender;
-
-    LPCTSTR getLogLevelStr(Logger::LogLevel level) {
-        switch (level) {
-        case Logger::LOG_TRACE:
-            return _T("TRACE");
-        case Logger::LOG_INFO:
-            return _T("INFO");
-        case Logger::LOG_WARNING:
-            return _T("WARNING");
-        case Logger::LOG_ERROR:
-            return _T("ERROR");
-        }
-        return _T("UNKNOWN");
-    }
-
-    tstring retrieveModuleName() {
-        try {
-            return FileUtils::basename(SysInfo::getCurrentModulePath());
-        } catch (const std::exception&) {
-            return _T("Unknown");
-        }
-    }
-
-    TCHAR moduleName[MAX_PATH] = { 'U', 'n', 'k', 'o', 'w', 'n', TCHAR(0) };
-
-    const LPCTSTR format = _T("[%04u/%02u/%02u %02u:%02u:%02u.%03u, %s (PID: %u, TID: %u), %s:%u (%s)]\n\t%s: %s\n");
-
-    enum State { NotInitialized, Initializing, Initialized };
-    State state = NotInitialized;
-}
-
-
-LogEvent::LogEvent() {
-    memset(this, 0, sizeof(*this));
-    moduleName = tstring();
-    logLevel = tstring();
-    fileName = tstring();
-    funcName = tstring();
-    message = tstring();
-}
-
-
-StderrLogAppender::StderrLogAppender() {
-}
-
-
-/*static*/
-Logger& Logger::defaultLogger() {
-    Logger* reply = reinterpret_cast<Logger*>(defaultLoggerMemory);
-
-    if (!reply->appender) {
-        // Memory leak by design. Not an issue at all as this is global
-        // object. OS will do resources clean up anyways when application
-        // terminates and the default log appender should live as long as
-        // application lives.
-        reply->appender = new (defaultLogAppenderMemory) StderrLogAppender();
-    }
-
-    if (Initializing == state) {
-        // Recursive call to Logger::defaultLogger.
-        moduleName[0] = TCHAR(0);
-    } else if (NotInitialized == state) {
-        state = Initializing;
-
-        tstring mname = retrieveModuleName();
-        mname.resize(_countof(moduleName) - 1);
-        std::memcpy(moduleName, mname.c_str(), mname.size());
-        moduleName[mname.size()] = TCHAR(0);
-
-        // if JPACKAGE_DEBUG environment variable is NOT set to "true" disable
-        // logging.
-        if (SysInfo::getEnvVariable(std::nothrow,
-                L"JPACKAGE_DEBUG") != L"true") {
-            reply->appender = &nopLogApender;
-        }
-
-        state = Initialized;
-    }
-
-    return *reply;
-}
-
-Logger::Logger(LogAppender& appender, LogLevel logLevel)
-        : level(logLevel), appender(&appender) {
-}
-
-void Logger::setLogLevel(LogLevel logLevel) {
-    level = logLevel;
-}
-
-Logger::~Logger() {
-}
-
-
-bool Logger::isLoggable(LogLevel logLevel) const {
-    return logLevel >= level;
-}
-
-void Logger::log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
-        LPCTSTR funcName, const tstring& message) const {
-    LogEvent logEvent;
-
-    // [YYYY/MM/DD HH:MM:SS.ms, <module> (PID: processID, TID: threadID),
-    // fileName:lineNum (funcName)] <tab>LEVEL: message
-    GetLocalTime(&logEvent.ts);
-
-    logEvent.pid = GetCurrentProcessId();
-    logEvent.tid = GetCurrentThreadId();
-    logEvent.moduleName = moduleName;
-    logEvent.fileName = FileUtils::basename(fileName);
-    logEvent.funcName = funcName;
-    logEvent.logLevel = getLogLevelStr(logLevel);
-    logEvent.lineNum = lineNum;
-    logEvent.message = message;
-
-    appender->append(logEvent);
-}
-
-
-void StderrLogAppender::append(const LogEvent& v)
-{
-    const tstring out = tstrings::unsafe_format(format,
-        unsigned(v.ts.wYear), unsigned(v.ts.wMonth), unsigned(v.ts.wDay),
-        unsigned(v.ts.wHour), unsigned(v.ts.wMinute), unsigned(v.ts.wSecond),
-                unsigned(v.ts.wMilliseconds),
-        v.moduleName.c_str(), v.pid, v.tid,
-        v.fileName.c_str(), v.lineNum, v.funcName.c_str(),
-        v.logLevel.c_str(),
-        v.message.c_str());
-
-    std::cerr << tstrings::toUtf8(out);
-}
-
-
-// Logger::ScopeTracer
-Logger::ScopeTracer::ScopeTracer(Logger &logger, LogLevel logLevel,
-        LPCTSTR fileName, int lineNum, LPCTSTR funcName,
-        const tstring& scopeName) : log(logger), level(logLevel),
-        file(fileName), line(lineNum),
-        func(funcName), scope(scopeName), needLog(logger.isLoggable(logLevel)) {
-    if (needLog) {
-        log.log(level, file.c_str(), line, func.c_str(),
-                tstrings::any() << "Entering " << scope);
-    }
-}
-
-Logger::ScopeTracer::~ScopeTracer() {
-    if (needLog) {
-        // we don't know what line is end of scope at, so specify line 0
-        // and add note about line when the scope begins
-        log.log(level, file.c_str(), 0, func.c_str(),
-                tstrings::any() << "Exiting " << scope << " (entered at "
-                << FileUtils::basename(file) << ":" << line << ")");
-    }
-}
--- a/src/jdk.jpackage/windows/native/libjpackage/Log.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef __LOG_H_INCLUDED_
-#define __LOG_H_INCLUDED_
-
-#include <windows.h>
-#include "tstrings.h"
-
-
-/* Default logger (Logger::defaultLogger()) writes log messages to
- * the default log file.
- * Common scenario:
- *   - main() function configures default logger:
- *       FileLogAppender appender(_T("my_log_filename.log"));
- *       Logger::defaultLogger().setAppender(appender);
- *       Logger::defaultLogger().setLogLevel(LOG_INFO);
- * If the default file name and log level are not set,
- *  _T("jusched.log")/LOG_TRACE are used.
- *
- * Logger fileName specifies only file name,
- * full path for the log file depends on the platform
- * (usually value of the TMP env. var)
- */
-
-struct LogEvent {
-    SYSTEMTIME ts;
-    long tid;
-    long pid;
-    tstring moduleName;
-    tstring logLevel;
-    tstring fileName;
-    int lineNum;
-    tstring funcName;
-    tstring message;
-
-    LogEvent();
-};
-
-
-class LogAppender {
-public:
-    virtual ~LogAppender() {
-    }
-    virtual void append(const LogEvent& v) = 0;
-};
-
-
-class NopLogAppender: public LogAppender {
-public:
-    virtual void append(const LogEvent& v) {};
-};
-
-
-class TeeLogAppender: public LogAppender {
-public:
-    TeeLogAppender(LogAppender* first, LogAppender* second):
-            first(first), second(second) {
-    }
-    virtual ~TeeLogAppender() {
-    }
-    virtual void append(const LogEvent& v) {
-        if (first) {
-            first->append(v);
-        }
-        if (second) {
-            second->append(v);
-        }
-    }
-private:
-    LogAppender* first;
-    LogAppender* second;
-};
-
-
-/**
- * Writes log events to stderr.
- */
-class StderrLogAppender: public LogAppender {
-public:
-    explicit StderrLogAppender();
-
-    virtual void append(const LogEvent& v);
-};
-
-
-class Logger {
-public:
-    enum LogLevel {
-        LOG_TRACE,
-        LOG_INFO,
-        LOG_WARNING,
-        LOG_ERROR
-    };
-
-    static Logger& defaultLogger();
-
-    explicit Logger(LogAppender& appender, LogLevel logLevel = LOG_TRACE);
-    ~Logger();
-
-    LogAppender& setAppender(LogAppender& v) {
-        LogAppender& oldAppender = *appender;
-        appender = &v;
-        return oldAppender;
-    }
-
-    LogAppender& getAppender() const {
-        return *appender;
-    }
-
-    void setLogLevel(LogLevel logLevel);
-
-    bool isLoggable(LogLevel logLevel) const ;
-    void log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
-            LPCTSTR funcName, const tstring& message) const;
-    void log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
-            LPCTSTR funcName, const tstrings::any& message) const {
-        return log(logLevel, fileName, lineNum, funcName, message.tstr());
-    }
-    void log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
-            LPCTSTR funcName, tstring::const_pointer message) const {
-        return log(logLevel, fileName, lineNum, funcName, tstring(message));
-    }
-
-    // internal class for scope tracing
-    class ScopeTracer {
-    public:
-        ScopeTracer(Logger &logger, LogLevel logLevel, LPCTSTR fileName,
-                int lineNum, LPCTSTR funcName, const tstring& scopeName);
-        ~ScopeTracer();
-
-    private:
-        const Logger &log;
-        const LogLevel level;
-        const bool needLog;
-        const tstring file;
-        const int line;
-        const tstring func;
-        const tstring scope;
-    };
-
-private:
-    LogLevel level;
-    LogAppender* appender;
-};
-
-
-// base logging macro
-#define LOGGER_LOG(logger, logLevel, message) \
-    do { \
-        if (logger.isLoggable(logLevel)) { \
-            logger.log(logLevel, _T(__FILE__), __LINE__, _T(__FUNCTION__), message); \
-        } \
-    } while(false)
-
-
-// custom logger macros
-#define LOGGER_TRACE(logger, message)   LOGGER_LOG(logger, Logger::LOG_TRACE, message)
-#define LOGGER_INFO(logger, message)    LOGGER_LOG(logger, Logger::LOG_INFO, message)
-#define LOGGER_WARNING(logger, message) LOGGER_LOG(logger, Logger::LOG_WARNING, message)
-#define LOGGER_ERROR(logger, message)   LOGGER_LOG(logger, Logger::LOG_ERROR, message)
-// scope tracing macros
-#define LOGGER_TRACE_SCOPE(logger, scopeName) \
-    Logger::ScopeTracer tracer__COUNTER__(logger, Logger::LOG_TRACE, _T(__FILE__), __LINE__, _T(__FUNCTION__), scopeName)
-#define LOGGER_TRACE_FUNCTION(logger)   LOGGER_TRACE_SCOPE(logger, _T(__FUNCTION__))
-
-
-// default logger macros
-#define LOG_TRACE(message)              LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_TRACE, message)
-#define LOG_INFO(message)               LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_INFO, message)
-#define LOG_WARNING(message)            LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_WARNING, message)
-#define LOG_ERROR(message)              LOGGER_LOG(Logger::defaultLogger(), Logger::LOG_ERROR, message)
-// scope tracing macros
-// logs (_T("Entering ") + scopeName) at the beging, (_T("Exiting ") + scopeName) at the end of scope
-#define LOG_TRACE_SCOPE(scopeName)      LOGGER_TRACE_SCOPE(Logger::defaultLogger(), scopeName)
-// logs (_T("Entering ") + functionName) at the beging, (_T("Exiting ") + __FUNCTION__) at the end of scope
-#define LOG_TRACE_FUNCTION()            LOGGER_TRACE_FUNCTION(Logger::defaultLogger())
-
-
-#endif // __LOG_H_INCLUDED_
--- a/src/jdk.jpackage/windows/native/libjpackage/ResourceEditor.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include <algorithm>
-#include <fstream>
-#include "ResourceEditor.h"
-#include "WinErrorHandling.h"
-#include "Log.h"
-
-
-ResourceEditor::FileLock::FileLock(const std::wstring& binaryPath) {
-    h = BeginUpdateResource(binaryPath.c_str(), FALSE);
-    if (NULL == h) {
-        JP_THROW(SysError(tstrings::any() << "BeginUpdateResource("
-                    << binaryPath << ") failed", BeginUpdateResource));
-    }
-
-    discard(false);
-}
-
-
-ResourceEditor::FileLock::~FileLock() {
-    if (!EndUpdateResource(h, theDiscard)) {
-        JP_NO_THROW(JP_THROW(SysError(tstrings::any()
-            << "EndUpdateResource(" << h << ") failed.", EndUpdateResource)));
-    }
-}
-
-
-ResourceEditor::ResourceEditor() {
-    language(MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)).type(unsigned(0)).id(unsigned(0));
-}
-
-
-ResourceEditor& ResourceEditor::type(unsigned v) {
-    return type(MAKEINTRESOURCE(v));
-}
-
-
-ResourceEditor& ResourceEditor::type(LPCWSTR v) {
-    if (IS_INTRESOURCE(v)) {
-        std::wostringstream printer;
-        printer << L"#" << reinterpret_cast<size_t>(v);
-        theType = printer.str();
-        theTypePtr = MAKEINTRESOURCE(static_cast<DWORD>(reinterpret_cast<DWORD_PTR>(v)));
-    } else {
-        theType = v;
-        theTypePtr = theType.c_str();
-    }
-    return *this;
-}
-
-
-ResourceEditor& ResourceEditor::id(unsigned v) {
-    return id(MAKEINTRESOURCE(v));
-}
-
-
-ResourceEditor& ResourceEditor::id(LPCWSTR v) {
-    if (IS_INTRESOURCE(v)) {
-        std::wostringstream printer;
-        printer << L"#" << reinterpret_cast<size_t>(v);
-        theId = printer.str();
-    } else {
-        theId = v;
-        theIdPtr = theId.c_str();
-    }
-    return *this;
-}
-
-
-ResourceEditor& ResourceEditor::apply(const FileLock& dstBinary,
-                            std::istream& srcStream, std::streamsize size) {
-
-    typedef std::vector<BYTE> ByteArray;
-    ByteArray buf;
-    if (size <= 0) {
-        // Read the entire stream.
-        buf = ByteArray((std::istreambuf_iterator<char>(srcStream)),
-                                            std::istreambuf_iterator<char>());
-    } else {
-        buf.resize(size_t(size));
-        srcStream.read(reinterpret_cast<char*>(buf.data()), size);
-    }
-
-    auto reply = UpdateResource(dstBinary.get(), theTypePtr, theIdPtr, lang,
-                                buf.data(), static_cast<DWORD>(buf.size()));
-    if (reply == FALSE) {
-        JP_THROW(SysError("UpdateResource() failed", UpdateResource));
-    }
-
-    return *this;
-}
-
-
-ResourceEditor& ResourceEditor::apply(const FileLock& dstBinary,
-                                                const std::wstring& srcFile) {
-    std::ifstream input(srcFile, std::ios_base::binary);
-    input.exceptions(std::ios::failbit | std::ios::badbit);
-    return apply(dstBinary, input);
-}
--- a/src/jdk.jpackage/windows/native/libjpackage/ResourceEditor.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef RESOURCEEDITOR_H
-#define RESOURCEEDITOR_H
-
-#include <windows.h>
-#include <vector>
-#include <string>
-
-
-class ResourceEditor {
-public:
-    class FileLock {
-    public:
-        FileLock(const std::wstring& binaryPath);
-        ~FileLock();
-
-        HANDLE get() const {
-            return h;
-        }
-
-        void discard(bool v = true) {
-            theDiscard = v;
-        }
-
-    private:
-        FileLock(const FileLock&);
-        FileLock& operator=(const FileLock&);
-    private:
-        HANDLE h;
-        bool theDiscard;
-    };
-
-public:
-    ResourceEditor();
-
-    /**
-     * Set the language identifier of the resource to be updated.
-     */
-    ResourceEditor& language(unsigned v) {
-        lang = v;
-        return *this;
-    }
-
-    /**
-     * Set the resource type to be updated.
-     */
-    ResourceEditor& type(unsigned v);
-
-    /**
-     * Set the resource type to be updated.
-     */
-    ResourceEditor& type(LPCWSTR v);
-
-    /**
-     * Set resource ID.
-     */
-    ResourceEditor& id(unsigned v);
-
-    /**
-     * Set resource ID.
-     */
-    ResourceEditor& id(LPCWSTR v);
-
-    /**
-     * Relaces resource configured in the given binary with the given data stream.
-     */
-    ResourceEditor& apply(const FileLock& dstBinary, std::istream& srcStream, std::streamsize size=0);
-
-    /**
-     * Relaces resource configured in the given binary with contents of
-     * the given binary file.
-     */
-    ResourceEditor& apply(const FileLock& dstBinary, const std::wstring& srcFile);
-
-private:
-    unsigned lang;
-    std::wstring theId;
-    LPCWSTR theIdPtr;
-    std::wstring theType;
-    LPCWSTR theTypePtr;
-};
-
-#endif // #ifndef RESOURCEEDITOR_H
--- a/src/jdk.jpackage/windows/native/libjpackage/SourceCodePos.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-
-#ifndef SourceCodePos_h
-#define SourceCodePos_h
-
-
-//
-// Position in source code.
-//
-
-struct SourceCodePos
-{
-    SourceCodePos(const char* fl, const char* fnc, int l):
-                                                file(fl), func(fnc), lno(l)
-    {
-    }
-
-    const char* file;
-    const char* func;
-    int lno;
-};
-
-
-// Initializes SourceCodePos instance with the
-// information from the point of calling.
-#define JP_SOURCE_CODE_POS SourceCodePos(__FILE__, __FUNCTION__, __LINE__)
-
-
-#endif // #ifndef SourceCodePos_h
--- a/src/jdk.jpackage/windows/native/libjpackage/SysInfo.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-
-#ifndef SYSINFO_H
-#define SYSINFO_H
-
-#include "tstrings.h"
-
-
-//
-// This namespace provides information about environment in which
-// the current application runs.
-// It is for general purpose use.
-// Functions in this namespaces are just queries about the environment.
-// Functions that change the existing environment like file or directory
-// creation should not be added to this namespace.
-//
-namespace SysInfo {
-    /**
-     * Returns temp dir (for the current user).
-     */
-    tstring getTempDir();
-
-    /**
-     * Returns absolute path to the process executable.
-     */
-    tstring getProcessModulePath();
-
-    /**
-     * Returns absolute path to the current executable module.
-     */
-    tstring getCurrentModulePath();
-
-    enum CommandArgProgramNameMode {
-        IncludeProgramName,
-        ExcludeProgramName
-    };
-    /**
-     * Retrieves the command-line arguments for the current process.
-     * With IncludeProgramName option returns result similar to argv/argc.
-     * With ExcludeProgramName option program name
-     *  (the 1st element of command line)
-     * is excluded.
-     */
-    tstring_array getCommandArgs(
-            CommandArgProgramNameMode progNameMode = ExcludeProgramName);
-
-    /**
-     * Returns value of environment variable with the given name.
-     * Throws exception if variable is not set or any other error occurred
-     * reading the value.
-     */
-    tstring getEnvVariable(const tstring& name);
-
-    /**
-     * Returns value of environment variable with the given name.
-     * Returns value of 'defValue' parameter if variable is not set or any
-     * other error occurred reading the value.
-     */
-    tstring getEnvVariable(const std::nothrow_t&, const tstring& name,
-            const tstring& defValue=tstring());
-
-    /**
-     * Returns 'true' if environment variable with the given name is set.
-     */
-    bool isEnvVariableSet(const tstring& name);
-}
-
-#endif // SYSINFO_H
--- a/src/jdk.jpackage/windows/native/libjpackage/UniqueHandle.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef UNIQUEHANDLE_H
-#define UNIQUEHANDLE_H
-
-#include <windows.h>
-#include <memory>
-
-
-struct WndHandleDeleter {
-    typedef HANDLE pointer;
-
-    void operator()(HANDLE h) {
-        ::CloseHandle(h);
-    }
-};
-
-typedef std::unique_ptr<HANDLE, WndHandleDeleter> UniqueHandle;
-
-#endif // #ifndef UNIQUEHANDLE_H
--- a/src/jdk.jpackage/windows/native/libjpackage/Utils.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include "Windows.h"
-#include "Utils.h"
-
-#define BUFFER_SIZE 4096
-
-wstring GetStringFromJString(JNIEnv *pEnv, jstring jstr) {
-    const jchar *pJChars = pEnv->GetStringChars(jstr, NULL);
-    if (pJChars == NULL) {
-        return wstring(L"");
-    }
-
-    wstring wstr(pJChars);
-
-    pEnv->ReleaseStringChars(jstr, pJChars);
-
-    return wstr;
-}
-
-jstring GetJStringFromString(JNIEnv *pEnv,
-            const jchar *unicodeChars, jsize len) {
-    return pEnv->NewString(unicodeChars, len);
-}
-
-wstring GetLongPath(wstring path) {
-    wstring result(L"");
-
-    size_t len = path.length();
-    if (len > 1) {
-        if (path.at(len - 1) == '\\') {
-            path.erase(len - 1);
-        }
-    }
-
-    TCHAR *pBuffer = new TCHAR[BUFFER_SIZE];
-    if (pBuffer != NULL) {
-        DWORD dwResult = GetLongPathName(path.c_str(), pBuffer, BUFFER_SIZE);
-        if (dwResult > 0 && dwResult < BUFFER_SIZE) {
-            result = wstring(pBuffer);
-        } else {
-            delete [] pBuffer;
-            pBuffer = new TCHAR[dwResult];
-            if (pBuffer != NULL) {
-                DWORD dwResult2 =
-                        GetLongPathName(path.c_str(), pBuffer, dwResult);
-                if (dwResult2 == (dwResult - 1)) {
-                    result = wstring(pBuffer);
-                }
-            }
-        }
-
-        if (pBuffer != NULL) {
-            delete [] pBuffer;
-        }
-    }
-
-    return result;
-}
--- a/src/jdk.jpackage/windows/native/libjpackage/Utils.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef UTILS_H
-#define UTILS_H
-
-#include <string>
-#include "jni.h"
-
-using namespace std;
-
-wstring GetStringFromJString(JNIEnv *pEnv, jstring jstr);
-jstring GetJStringFromString(JNIEnv *pEnv, const jchar *unicodeChars,
-        jsize len);
-
-wstring GetLongPath(wstring path);
-
-#endif // UTILS_H
--- a/src/jdk.jpackage/windows/native/libjpackage/VersionInfoSwap.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,285 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.
- */
-
-#include "VersionInfoSwap.h"
-
-#include <stdio.h>
-#include <tchar.h>
-
-#include <windows.h>
-#include <stdio.h>
-#include <Strsafe.h>
-#include <fstream>
-#include <locale>
-#include <codecvt>
-
-using namespace std;
-
-/*
- * [Property file] contains key/value pairs
- * The swap tool uses these pairs to create new version resource
- *
- * See MSDN docs for VS_VERSIONINFO structure that
- * depicts organization of data in this version resource
- *    https://msdn.microsoft.com/en-us/library/ms647001(v=vs.85).aspx
- *
- * The swap tool makes changes in [Executable file]
- * The tool assumes that the executable file has no version resource
- * and it adds new resource in the executable file.
- * If the executable file has an existing version resource, then
- * the existing version resource will be replaced with new one.
- */
-
-VersionInfoSwap::VersionInfoSwap(wstring executableProperties,
-        wstring launcher) {
-    m_executableProperties = executableProperties;
-    m_launcher = launcher;
-}
-
-bool VersionInfoSwap::PatchExecutable() {
-    bool b = LoadFromPropertyFile();
-    if (!b) {
-        return false;
-    }
-
-    ByteBuffer buf;
-    b = CreateNewResource(&buf);
-    if (!b) {
-        return false;
-    }
-
-    b = this->UpdateResource(buf.getPtr(), static_cast<DWORD> (buf.getPos()));
-    if (!b) {
-        return false;
-    }
-
-    return true;
-}
-
-bool VersionInfoSwap::LoadFromPropertyFile() {
-    wifstream stream(m_executableProperties.c_str());
-
-    const locale empty_locale = locale::empty();
-    const locale utf8_locale =
-            locale(empty_locale, new codecvt_utf8<wchar_t>());
-    stream.imbue(utf8_locale);
-
-    if (stream.is_open() == true) {
-        int lineNumber = 1;
-        while (stream.eof() == false) {
-            wstring line;
-            getline(stream, line);
-
-            // # at the first character will comment out the line.
-            if (line.empty() == false && line[0] != '#') {
-                wstring::size_type pos = line.find('=');
-                if (pos != wstring::npos) {
-                    wstring name = line.substr(0, pos);
-                    wstring value = line.substr(pos + 1);
-                    m_props[name] = value;
-                }
-            }
-            lineNumber++;
-        }
-        return true;
-    }
-
-    return false;
-}
-
-/*
- * Creates new version resource
- *
- * MSND docs for VS_VERSION_INFO structure
- *     https://msdn.microsoft.com/en-us/library/ms647001(v=vs.85).aspx
- */
-bool VersionInfoSwap::CreateNewResource(ByteBuffer *buf) {
-    size_t versionInfoStart = buf->getPos();
-    buf->AppendWORD(0);
-    buf->AppendWORD(sizeof VS_FIXEDFILEINFO);
-    buf->AppendWORD(0);
-    buf->AppendString(TEXT("VS_VERSION_INFO"));
-    buf->Align(4);
-
-    VS_FIXEDFILEINFO fxi;
-    if (!FillFixedFileInfo(&fxi)) {
-        return false;
-    }
-    buf->AppendBytes((BYTE*) & fxi, sizeof (VS_FIXEDFILEINFO));
-    buf->Align(4);
-
-    // String File Info
-    size_t stringFileInfoStart = buf->getPos();
-    buf->AppendWORD(0);
-    buf->AppendWORD(0);
-    buf->AppendWORD(1);
-    buf->AppendString(TEXT("StringFileInfo"));
-    buf->Align(4);
-
-    // String Table
-    size_t stringTableStart = buf->getPos();
-    buf->AppendWORD(0);
-    buf->AppendWORD(0);
-    buf->AppendWORD(1);
-
-    // "040904B0" = LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP
-    buf->AppendString(TEXT("040904B0"));
-    buf->Align(4);
-
-    // Strings
-    vector<wstring> keys;
-    for (map<wstring, wstring>::const_iterator it =
-            m_props.begin(); it != m_props.end(); ++it) {
-        keys.push_back(it->first);
-    }
-
-    for (size_t index = 0; index < keys.size(); index++) {
-        wstring name = keys[index];
-        wstring value = m_props[name];
-
-        size_t stringStart = buf->getPos();
-        buf->AppendWORD(0);
-        buf->AppendWORD(static_cast<WORD> (value.length()));
-        buf->AppendWORD(1);
-        buf->AppendString(name);
-        buf->Align(4);
-        buf->AppendString(value);
-        buf->ReplaceWORD(stringStart,
-                static_cast<WORD> (buf->getPos() - stringStart));
-        buf->Align(4);
-    }
-
-    buf->ReplaceWORD(stringTableStart,
-            static_cast<WORD> (buf->getPos() - stringTableStart));
-    buf->ReplaceWORD(stringFileInfoStart,
-            static_cast<WORD> (buf->getPos() - stringFileInfoStart));
-
-    // VarFileInfo
-    size_t varFileInfoStart = buf->getPos();
-    buf->AppendWORD(1);
-    buf->AppendWORD(0);
-    buf->AppendWORD(1);
-    buf->AppendString(TEXT("VarFileInfo"));
-    buf->Align(4);
-
-    buf->AppendWORD(0x24);
-    buf->AppendWORD(0x04);
-    buf->AppendWORD(0x00);
-    buf->AppendString(TEXT("Translation"));
-    buf->Align(4);
-    // "000004B0" = LANG_NEUTRAL/SUBLANG_ENGLISH_US, Unicode CP
-    buf->AppendWORD(0x0000);
-    buf->AppendWORD(0x04B0);
-
-    buf->ReplaceWORD(varFileInfoStart,
-            static_cast<WORD> (buf->getPos() - varFileInfoStart));
-    buf->ReplaceWORD(versionInfoStart,
-            static_cast<WORD> (buf->getPos() - versionInfoStart));
-
-    return true;
-}
-
-bool VersionInfoSwap::FillFixedFileInfo(VS_FIXEDFILEINFO *fxi) {
-    wstring fileVersion;
-    wstring productVersion;
-    int ret;
-
-    fileVersion = m_props[TEXT("FileVersion")];
-    productVersion = m_props[TEXT("ProductVersion")];
-
-    unsigned fv_1 = 0, fv_2 = 0, fv_3 = 0, fv_4 = 0;
-    unsigned pv_1 = 0, pv_2 = 0, pv_3 = 0, pv_4 = 0;
-
-    ret = _stscanf_s(fileVersion.c_str(),
-            TEXT("%d.%d.%d.%d"), &fv_1, &fv_2, &fv_3, &fv_4);
-    if (ret <= 0 || ret > 4) {
-        return false;
-    }
-
-    ret = _stscanf_s(productVersion.c_str(),
-            TEXT("%d.%d.%d.%d"), &pv_1, &pv_2, &pv_3, &pv_4);
-    if (ret <= 0 || ret > 4) {
-        return false;
-    }
-
-    fxi->dwSignature = 0xFEEF04BD;
-    fxi->dwStrucVersion = 0x00010000;
-
-    fxi->dwFileVersionMS = MAKELONG(fv_2, fv_1);
-    fxi->dwFileVersionLS = MAKELONG(fv_4, fv_3);
-    fxi->dwProductVersionMS = MAKELONG(pv_2, pv_1);
-    fxi->dwProductVersionLS = MAKELONG(pv_4, pv_3);
-
-    fxi->dwFileFlagsMask = 0;
-    fxi->dwFileFlags = 0;
-    fxi->dwFileOS = VOS_NT_WINDOWS32;
-
-    wstring exeExt =
-            m_launcher.substr(m_launcher.find_last_of(TEXT(".")));
-    if (exeExt == TEXT(".exe")) {
-        fxi->dwFileType = VFT_APP;
-    } else if (exeExt == TEXT(".dll")) {
-        fxi->dwFileType = VFT_DLL;
-    } else {
-        fxi->dwFileType = VFT_UNKNOWN;
-    }
-    fxi->dwFileSubtype = 0;
-
-    fxi->dwFileDateLS = 0;
-    fxi->dwFileDateMS = 0;
-
-    return true;
-}
-
-/*
- * Adds new resource in the executable
- */
-bool VersionInfoSwap::UpdateResource(LPVOID lpResLock, DWORD size) {
-
-    HANDLE hUpdateRes;
-    BOOL r;
-
-    hUpdateRes = ::BeginUpdateResource(m_launcher.c_str(), FALSE);
-    if (hUpdateRes == NULL) {
-        return false;
-    }
-
-    r = ::UpdateResource(hUpdateRes,
-            RT_VERSION,
-            MAKEINTRESOURCE(VS_VERSION_INFO),
-            MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
-            lpResLock,
-            size);
-
-    if (!r) {
-        return false;
-    }
-
-    if (!::EndUpdateResource(hUpdateRes, FALSE)) {
-        return false;
-    }
-
-    return true;
-}
--- a/src/jdk.jpackage/windows/native/libjpackage/VersionInfoSwap.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2015, 2019, 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.
- */
-
-#ifndef VERSIONINFOSWAP_H
-#define VERSIONINFOSWAP_H
-
-#include "ByteBuffer.h"
-#include <map>
-
-using namespace std;
-
-class VersionInfoSwap {
-public:
-    VersionInfoSwap(wstring executableProperties, wstring launcher);
-
-    bool PatchExecutable();
-
-private:
-    wstring m_executableProperties;
-    wstring m_launcher;
-
-    map<wstring, wstring> m_props;
-
-    bool LoadFromPropertyFile();
-    bool CreateNewResource(ByteBuffer *buf);
-    bool UpdateResource(LPVOID lpResLock, DWORD size);
-    bool FillFixedFileInfo(VS_FIXEDFILEINFO *fxi);
-};
-
-#endif // VERSIONINFOSWAP_H
\ No newline at end of file
--- a/src/jdk.jpackage/windows/native/libjpackage/WinErrorHandling.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include "WinErrorHandling.h"
-#include "Log.h"
-#include "SysInfo.h"
-#include "FileUtils.h"
-
-
-namespace {
-
-std::string makeMessage(const std::string& msg, const char* label,
-                                            const void* c, DWORD errorCode) {
-    std::ostringstream err;
-    err << (label ? label : "Some error") << " [" << errorCode << "]";
-
-    HMODULE hmodule = NULL;
-    if (c) {
-        GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
-                | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
-                reinterpret_cast<LPCTSTR>(c), &hmodule);
-
-        if (!hmodule) {
-            LOG_WARNING(tstrings::any() << "GetModuleHandleEx() failed for "
-                    << c << " address.");
-        }
-    }
-    if (hmodule || !c) {
-        err << "(" << SysError::getSysErrorMessage(errorCode, hmodule) << ")";
-    }
-
-    return joinErrorMessages(msg, err.str());
-}
-
-
-std::wstring getSystemMessageDescription(DWORD messageId, HMODULE moduleHandle) {
-    LPWSTR pMsg = NULL;
-    std::wstring descr;
-
-    // we always retrieve UNICODE description from system,
-    // convert it to utf8 if UNICODE is not defined
-
-    while (true) {
-        DWORD res = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
-                | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS
-                | (moduleHandle != NULL ? FORMAT_MESSAGE_FROM_HMODULE : 0),
-                moduleHandle, messageId, 0, (LPWSTR)&pMsg, 0, NULL);
-        if (res > 0) {
-            // replace all non-printed chars with space
-            for (DWORD i=0; i<res; i++) {
-                if (pMsg[i] < L' ') {
-                    pMsg[i] = L' ';
-                }
-            }
-            // trim right (spaces and dots)
-            for (DWORD i=res; i>0; i--) {
-                if (pMsg[i] > L' ' && pMsg[i] != L'.') {
-                    break;
-                }
-                pMsg[i] = 0;
-            }
-
-            descr = pMsg;
-
-            LocalFree(pMsg);
-        } else {
-            // if we fail to get description for specific moduleHandle,
-            // try to get "common" description.
-            if (moduleHandle != NULL) {
-                moduleHandle = NULL;
-                continue;
-            }
-            descr = L"No description available";
-        }
-        break;
-    }
-
-    return descr;
-}
-
-} // namespace
-
-
-SysError::SysError(const tstrings::any& msg, const void* caller, DWORD ec,
-        const char* label):
-
-std::runtime_error(makeMessage(msg.str(), label, caller, ec)) {
-}
-
-std::wstring SysError::getSysErrorMessage(DWORD errCode, HMODULE moduleHandle) {
-    tstrings::any msg;
-    msg << "system error " << errCode
-        << " (" << getSystemMessageDescription(errCode, moduleHandle) << ")";
-    return msg.tstr();
-}
-
-std::wstring SysError::getComErrorMessage(HRESULT hr) {
-    HRESULT hrOrig = hr;
-    // for FACILITY_WIN32 facility we need to reset hiword
-    if(HRESULT_FACILITY(hr) == FACILITY_WIN32) {
-        hr = HRESULT_CODE(hr);
-    }
-    return tstrings::format(_T("COM error 0x%08X (%s)"), hrOrig,
-            getSystemMessageDescription(hr, NULL));
-}
--- a/src/jdk.jpackage/windows/native/libjpackage/WinErrorHandling.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-
-#ifndef WinErrorHandling_h
-#define WinErrorHandling_h
-
-
-#include "ErrorHandling.h"
-
-
-class SysError : public std::runtime_error {
-public:
-    SysError(const tstrings::any& msg, const void* caller,
-            DWORD errorCode=GetLastError(), const char* label="System error");
-
-    // returns string "system error <errCode> (error_description)"
-    // in UNICODE is not defined, the string returned is utf8-encoded
-    static std::wstring getSysErrorMessage(DWORD errCode = GetLastError(),
-            HMODULE moduleHandle = NULL);
-
-    // returns string "COM error 0x<hr> (error_description)"
-    // in UNICODE is not defined, the string returned is utf8-encoded
-    static std::wstring getComErrorMessage(HRESULT hr);
-};
-
-#endif // #ifndef WinErrorHandling_h
--- a/src/jdk.jpackage/windows/native/libjpackage/WinSysInfo.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include <windows.h>
-#include <shellapi.h>
-
-#include "WinSysInfo.h"
-#include "FileUtils.h"
-#include "WinErrorHandling.h"
-
-#pragma comment(lib, "Shell32")
-
-namespace SysInfo {
-
-tstring getTempDir() {
-    std::vector<TCHAR> buffer(MAX_PATH);
-    DWORD res = GetTempPath(static_cast<DWORD>(buffer.size()), buffer.data());
-    if (res > buffer.size()) {
-        buffer.resize(res);
-        GetTempPath(static_cast<DWORD>(buffer.size()), buffer.data());
-    }
-    return FileUtils::removeTrailingSlash(buffer.data());
-}
-
-namespace {
-
-template <class Func>
-tstring getSystemDirImpl(Func func, const std::string& label) {
-    std::vector<TCHAR> buffer(MAX_PATH);
-    for (int i=0; i<2; i++) {
-        DWORD res = func(buffer.data(), static_cast<DWORD>(buffer.size()));
-        if (!res) {
-            JP_THROW(SysError(label + " failed", func));
-        }
-        if (res < buffer.size()) {
-            return FileUtils::removeTrailingSlash(buffer.data());
-        }
-        buffer.resize(res + 1);
-    }
-    JP_THROW("Unexpected reply from" + label);
-}
-
-} // namespace
-
-tstring getSystem32Dir() {
-    return getSystemDirImpl(GetSystemDirectory, "GetSystemDirectory");
-}
-
-tstring getWIPath() {
-    return FileUtils::mkpath() << getSystem32Dir() << _T("msiexec.exe");
-}
-
-namespace {
-
-tstring getModulePath(HMODULE h)
-{
-    std::vector<TCHAR> buf(MAX_PATH);
-    DWORD len = 0;
-    while (true) {
-        len = GetModuleFileName(h, buf.data(), (DWORD)buf.size());
-        if (len < buf.size()) {
-            break;
-        }
-        // buffer is too small, increase it
-        buf.resize(buf.size() * 2);
-    }
-
-    if (len == 0) {
-        // error occured
-        JP_THROW(SysError("GetModuleFileName failed", GetModuleFileName));
-    }
-    return tstring(buf.begin(), buf.begin() + len);
-}
-
-} // namespace
-
-tstring getProcessModulePath() {
-    return getModulePath(NULL);
-}
-
-HMODULE getCurrentModuleHandle()
-{
-    // get module handle for the address of this function
-    LPCWSTR address = reinterpret_cast<LPCWSTR>(getCurrentModuleHandle);
-    HMODULE hmodule = NULL;
-    if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
-            | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, address, &hmodule))
-    {
-        JP_THROW(SysError(tstrings::any() << "GetModuleHandleExW failed",
-                GetModuleHandleExW));
-    }
-    return hmodule;
-}
-
-tstring getCurrentModulePath()
-{
-    return getModulePath(getCurrentModuleHandle());
-}
-
-tstring_array getCommandArgs(CommandArgProgramNameMode progNameMode)
-{
-    int argc = 0;
-    tstring_array result;
-
-    LPWSTR *parsedArgs = CommandLineToArgvW(GetCommandLineW(), &argc);
-    if (parsedArgs == NULL) {
-        JP_THROW(SysError("CommandLineToArgvW failed", CommandLineToArgvW));
-    }
-    // the 1st element contains program name
-    for (int i = progNameMode == ExcludeProgramName ? 1 : 0; i < argc; i++) {
-        result.push_back(parsedArgs[i]);
-    }
-    LocalFree(parsedArgs);
-
-    return result;
-}
-
-namespace {
-
-tstring getEnvVariableImpl(const tstring& name, bool* errorOccured=0) {
-    std::vector<TCHAR> buf(10);
-    SetLastError(ERROR_SUCCESS);
-    const DWORD size = GetEnvironmentVariable(name.c_str(), buf.data(),
-                                                            DWORD(buf.size()));
-    if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
-        if (errorOccured) {
-            *errorOccured = true;
-            return tstring();
-        }
-        JP_THROW(SysError(tstrings::any() << "GetEnvironmentVariable("
-            << name << ") failed. Variable not set", GetEnvironmentVariable));
-    }
-
-    if (size > buf.size()) {
-        buf.resize(size);
-        GetEnvironmentVariable(name.c_str(), buf.data(), DWORD(buf.size()));
-        if (GetLastError() != ERROR_SUCCESS) {
-            if (errorOccured) {
-                *errorOccured = true;
-                return tstring();
-            }
-            JP_THROW(SysError(tstrings::any() << "GetEnvironmentVariable("
-                            << name << ") failed", GetEnvironmentVariable));
-        }
-    }
-
-    if (errorOccured) {
-        *errorOccured = false;
-    }
-    return tstring(buf.data());
-}
-
-} // namespace
-
-tstring getEnvVariable(const tstring& name) {
-    return getEnvVariableImpl(name);
-}
-
-tstring getEnvVariable(const std::nothrow_t&, const tstring& name,
-                                                    const tstring& defValue) {
-    bool errorOccured = false;
-    const tstring reply = getEnvVariableImpl(name, &errorOccured);
-    if (errorOccured) {
-        return defValue;
-    }
-    return reply;
-}
-
-bool isEnvVariableSet(const tstring& name) {
-    TCHAR unused[1];
-    SetLastError(ERROR_SUCCESS);
-    GetEnvironmentVariable(name.c_str(), unused, _countof(unused));
-    return GetLastError() != ERROR_ENVVAR_NOT_FOUND;
-}
-
-} // end of namespace SysInfo
--- a/src/jdk.jpackage/windows/native/libjpackage/WinSysInfo.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-
-#ifndef WINSYSINFO_H
-#define WINSYSINFO_H
-
-#include "SysInfo.h"
-
-
-//
-// Windows specific SysInfo.
-//
-namespace SysInfo {
-    // gets Windows System folder. A typical path is C:\Windows\System32.
-    tstring getSystem32Dir();
-
-    // returns full path to msiexec.exe executable
-    tstring getWIPath();
-
-    // Returns handle of the current module (exe or dll).
-    // The function assumes this code is statically linked to the module.
-    HMODULE getCurrentModuleHandle();
-}
-
-
-#endif // WINSYSINFO_H
--- a/src/jdk.jpackage/windows/native/libjpackage/WindowsRegistry.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include <Windows.h>
-#include <strsafe.h>
-#include <tchar.h>
-#include <jni.h>
-
-#include "Utils.h"
-
-// Max value name size per MSDN plus NULL
-#define VALUE_NAME_SIZE 16384
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#undef jdk_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE
-#define jdk_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE 1L
-
-    /*
-     * Class:     jdk_jpackage_internal_WindowsRegistry
-     * Method:    readDwordValue
-     * Signature: (ILjava/lang/String;Ljava/lang/String;I)I
-     */
-    JNIEXPORT jint JNICALL
-            Java_jdk_jpackage_internal_WindowsRegistry_readDwordValue(
-            JNIEnv *pEnv, jclass c, jint key, jstring jSubKey,
-            jstring jValue, jint defaultValue) {
-        jint jResult = defaultValue;
-
-        if (key != jdk_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE) {
-            return jResult;
-        }
-
-        wstring subKey = GetStringFromJString(pEnv, jSubKey);
-        wstring value = GetStringFromJString(pEnv, jValue);
-
-        HKEY hSubKey = NULL;
-        LSTATUS status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey.c_str(), 0,
-                KEY_QUERY_VALUE, &hSubKey);
-        if (status == ERROR_SUCCESS) {
-            DWORD dwValue = 0;
-            DWORD cbData = sizeof (DWORD);
-            status = RegQueryValueEx(hSubKey, value.c_str(), NULL, NULL,
-                    (LPBYTE) & dwValue, &cbData);
-            if (status == ERROR_SUCCESS) {
-                jResult = (jint) dwValue;
-            }
-
-            RegCloseKey(hSubKey);
-        }
-
-        return jResult;
-    }
-
-    /*
-     * Class:     jdk_jpackage_internal_WindowsRegistry
-     * Method:    openRegistryKey
-     * Signature: (ILjava/lang/String;)J
-     */
-    JNIEXPORT jlong JNICALL
-            Java_jdk_jpackage_internal_WindowsRegistry_openRegistryKey(
-            JNIEnv *pEnv, jclass c, jint key, jstring jSubKey) {
-        if (key != jdk_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE) {
-            return 0;
-        }
-
-        wstring subKey = GetStringFromJString(pEnv, jSubKey);
-        HKEY hSubKey = NULL;
-        LSTATUS status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey.c_str(), 0,
-                KEY_QUERY_VALUE, &hSubKey);
-        if (status == ERROR_SUCCESS) {
-            return (jlong)hSubKey;
-        }
-
-        return 0;
-    }
-
-    /*
-     * Class:     jdk_jpackage_internal_WindowsRegistry
-     * Method:    enumRegistryValue
-     * Signature: (JI)Ljava/lang/String;
-     */
-    JNIEXPORT jstring JNICALL
-            Java_jdk_jpackage_internal_WindowsRegistry_enumRegistryValue(
-            JNIEnv *pEnv, jclass c, jlong lKey, jint jIndex) {
-        HKEY hKey = (HKEY)lKey;
-        TCHAR valueName[VALUE_NAME_SIZE] = {0}; // Max size per MSDN plus NULL
-        DWORD cchValueName = VALUE_NAME_SIZE;
-        LSTATUS status = RegEnumValue(hKey, (DWORD)jIndex, valueName,
-                &cchValueName, NULL, NULL, NULL, NULL);
-        if (status == ERROR_SUCCESS) {
-            size_t chLength = 0;
-            if (StringCchLength(valueName, VALUE_NAME_SIZE, &chLength)
-                    == S_OK) {
-                return GetJStringFromString(pEnv, valueName, (jsize)chLength);
-            }
-        }
-
-        return NULL;
-    }
-
-    /*
-     * Class:     jdk_jpackage_internal_WindowsRegistry
-     * Method:    closeRegistryKey
-     * Signature: (J)V
-     */
-    JNIEXPORT void JNICALL
-            Java_jdk_jpackage_internal_WindowsRegistry_closeRegistryKey(
-            JNIEnv *pEnc, jclass c, jlong lKey) {
-        HKEY hKey = (HKEY)lKey;
-        RegCloseKey(hKey);
-    }
-
-    /*
-     * Class:     jdk_jpackage_internal_WindowsRegistry
-     * Method:    comparePaths
-     * Signature: (Ljava/lang/String;Ljava/lang/String;)Z
-     */
-     JNIEXPORT jboolean JNICALL
-            Java_jdk_jpackage_internal_WindowsRegistry_comparePaths(
-            JNIEnv *pEnv, jclass c, jstring jPath1, jstring jPath2) {
-         wstring path1 = GetStringFromJString(pEnv, jPath1);
-         wstring path2 = GetStringFromJString(pEnv, jPath2);
-
-         path1 = GetLongPath(path1);
-         path2 = GetLongPath(path2);
-
-         if (path1.length() == 0 || path2.length() == 0) {
-             return JNI_FALSE;
-         }
-
-         if (path1.length() != path2.length()) {
-             return JNI_FALSE;
-         }
-
-         if (_tcsnicmp(path1.c_str(), path2.c_str(), path1.length()) == 0) {
-             return JNI_TRUE;
-         }
-
-         return JNI_FALSE;
-     }
-
-#ifdef __cplusplus
-}
-#endif
--- a/src/jdk.jpackage/windows/native/libjpackage/jpackage.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2011, 2019, 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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string>
-#include <windows.h>
-
-#include "ResourceEditor.h"
-#include "WinErrorHandling.h"
-#include "IconSwap.h"
-#include "VersionInfoSwap.h"
-#include "Utils.h"
-
-using namespace std;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-    /*
-     * Class:     jdk_jpackage_internal_WindowsAppImageBuilder
-     * Method:    iconSwap
-     * Signature: (Ljava/lang/String;Ljava/lang/String;)I
-     */
-    JNIEXPORT jint JNICALL
-            Java_jdk_jpackage_internal_WindowsAppImageBuilder_iconSwap(
-            JNIEnv *pEnv, jclass c, jstring jIconTarget, jstring jLauncher) {
-        wstring iconTarget = GetStringFromJString(pEnv, jIconTarget);
-        wstring launcher = GetStringFromJString(pEnv, jLauncher);
-
-        if (ChangeIcon(iconTarget, launcher)) {
-            return 0;
-        }
-
-        return 1;
-    }
-
-    /*
-     * Class:     jdk_jpackage_internal_WindowsAppImageBuilder
-     * Method:    versionSwap
-     * Signature: (Ljava/lang/String;Ljava/lang/String;)I
-     */
-    JNIEXPORT jint JNICALL
-            Java_jdk_jpackage_internal_WindowsAppImageBuilder_versionSwap(
-            JNIEnv *pEnv, jclass c, jstring jExecutableProperties,
-            jstring jLauncher) {
-
-        wstring executableProperties = GetStringFromJString(pEnv,
-                jExecutableProperties);
-        wstring launcher = GetStringFromJString(pEnv, jLauncher);
-
-        VersionInfoSwap vs(executableProperties, launcher);
-        if (vs.PatchExecutable()) {
-            return 0;
-        }
-
-        return 1;
-    }
-
-    /*
-     * Class:     jdk_jpackage_internal_WinExeBundler
-     * Method:    embedMSI
-     * Signature: (Ljava/lang/String;Ljava/lang/String;)I
-     */
-    JNIEXPORT jint JNICALL Java_jdk_jpackage_internal_WinExeBundler_embedMSI(
-            JNIEnv *pEnv, jclass c, jstring jexePath, jstring jmsiPath) {
-
-        const wstring exePath = GetStringFromJString(pEnv, jexePath);
-        const wstring msiPath = GetStringFromJString(pEnv, jmsiPath);
-
-        JP_TRY;
-
-        ResourceEditor()
-            .id(L"msi")
-            .type(RT_RCDATA)
-            .apply(ResourceEditor::FileLock(exePath), msiPath);
-
-        return 0;
-
-        JP_CATCH_ALL;
-
-        return 1;
-    }
-
-    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
-            LPVOID lpvReserved) {
-        return TRUE;
-    }
-
-#ifdef __cplusplus
-}
-#endif
--- a/src/jdk.jpackage/windows/native/libjpackage/tstrings.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,280 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdexcept>
-#include <algorithm>
-
-#include "tstrings.h"
-#include "ErrorHandling.h"
-
-
-namespace tstrings {
-
-/* Create formatted string
- */
-tstring unsafe_format(tstring::const_pointer format, ...) {
-    if (!format) {
-        throw std::invalid_argument("Destination buffer can't be NULL");
-    }
-
-    tstring fmtout;
-    int ret;
-    const int inc = 256;
-
-    va_list args;
-    va_start(args, format);
-    do {
-        fmtout.resize(fmtout.size() + inc);
-#ifdef _MSC_VER
-        ret = _vsntprintf_s(&*fmtout.begin(), fmtout.size(), _TRUNCATE, format, args);
-#else
-        // With g++ this compiles only with '-std=gnu++0x' option
-        ret = vsnprintf(&*fmtout.begin(), fmtout.size(), format, args);
-#endif
-    } while(-1 == ret);
-    va_end(args);
-
-    //update string size by actual value
-    fmtout.resize(ret);
-
-    return fmtout;
-}
-
-/*
- * Tests if two strings are equal according to CompareType.
- *
- * a - string to compare
- * b - string to compare
- * ct - CASE_SENSITIVE: case sensitive comparing type
- *      IGNORE_CASE: case insensitive comparing type
- */
-bool equals(const tstring& a, const tstring& b, const CompareType ct) {
-    if (IGNORE_CASE==ct) {
-        return toLower(a) == toLower(b);
-    }
-    return a == b;
-}
-
-bool startsWith(const tstring &str, const tstring &substr, const CompareType ct)
-{
-    if (str.size() < substr.size()) {
-        return false;
-    }
-    const tstring startOfStr = str.substr(0, substr.size());
-    return tstrings::equals(startOfStr, substr, ct);
-}
-
-bool endsWith(const tstring &str, const tstring &substr, const CompareType ct)
-{
-    if (str.size() < substr.size()) {
-        return false;
-    }
-    const tstring endOfStr = str.substr(str.size() - substr.size());
-    return tstrings::equals(endOfStr, substr, ct);
-}
-
-/*
- * Split string into a vector with given delimiter string
- *
- * strVector - string vector to store split tstring
- * str - string to split
- * delimiter - delimiter to split the string around
- * st - ST_ALL: return value includes an empty string
- *      ST_EXCEPT_EMPTY_STRING: return value does not include an empty string
- *
- * Note: It does not support multiple delimiters
- */
-void split(tstring_array &strVector, const tstring &str,
-          const tstring &delimiter, const SplitType st) {
-    tstring::size_type start = 0, end = 0, length = str.length();
-
-    if (length == 0 || delimiter.length() == 0) {
-        return;
-    }
-
-    end = str.find(delimiter, start);
-    while(end != tstring::npos) {
-        if(st == ST_ALL || end - start > 1 ) {
-            strVector.push_back(str.substr(start, end == tstring::npos ?
-                                                  tstring::npos : end - start));
-        }
-        start = end > (tstring::npos - delimiter.size()) ?
-                tstring::npos : end + delimiter.size();
-        end = str.find(delimiter, start);
-    }
-
-    if(st == ST_ALL || start < length) {
-        strVector.push_back(str.substr(start, length - start));
-    }
-}
-
-/*
- * Convert uppercase letters to lowercase
- */
-tstring toLower(const tstring& str) {
-    tstring lower(str);
-    tstring::iterator ok = std::transform(lower.begin(), lower.end(),
-                                          lower.begin(), tolower);
-    if (ok!=lower.end()) {
-        lower.resize(0);
-    }
-    return lower;
-}
-
-
-/*
- * Replace all substring occurrences in a tstring.
- * If 'str' or 'search' is empty the function returns 'str'.
- * The given 'str' remains unchanged in any case.
- * The function returns changed copy of 'str'.
- */
-tstring replace(const tstring &str, const tstring &search, const tstring &replace)
-{
-    if (search.empty()) {
-        return str;
-    }
-
-    tstring s(str);
-
-    for (size_t pos = 0; ; pos += replace.length()) {
-        pos = s.find(search, pos);
-        if (pos == tstring::npos) {
-            break;
-        }
-        s.erase(pos, search.length());
-        s.insert(pos, replace);
-    }
-    return s;
-}
-
-
-/*
- * Remove trailing spaces
- */
-
-tstring trim(const tstring& str, const tstring& whitespace) {
-    const size_t strBegin = str.find_first_not_of(whitespace);
-    if (strBegin == std::string::npos) {
-        return tstring(); // no content
-    }
-
-    const size_t  strEnd = str.find_last_not_of(whitespace);
-    const size_t strRange = strEnd - strBegin + 1;
-
-    return str.substr(strBegin, strRange);
-}
-
-} // namespace tstrings
-
-
-#ifdef TSTRINGS_WITH_WCHAR
-namespace tstrings {
-
-namespace {
-/*
- * Converts UTF16-encoded string into multi-byte string of the given encoding.
- */
-std::string toMultiByte(const std::wstring& utf16str, int encoding) {
-    std::string reply;
-    do {
-        int cm = WideCharToMultiByte(encoding,
-                                    0,
-                                    utf16str.c_str(),
-                                    int(utf16str.size()),
-                                    NULL,
-                                    0,
-                                    NULL,
-                                    NULL);
-        if (cm < 0) {
-            JP_THROW("Unexpected reply from WideCharToMultiByte()");
-        }
-        if (0 == cm) {
-            break;
-        }
-
-        reply.resize(cm);
-        int cm2 = WideCharToMultiByte(encoding,
-                                    0,
-                                    utf16str.c_str(),
-                                    int(utf16str.size()),
-                                    &*reply.begin(),
-                                    cm,
-                                    NULL,
-                                    NULL);
-        if (cm != cm2) {
-            JP_THROW("Unexpected reply from WideCharToMultiByte()");
-        }
-    } while(0);
-
-    return reply;
-}
-
-/*
- * Converts multi-byte string of the given encoding into UTF16-encoded string.
- */
-std::wstring fromMultiByte(const std::string& str, int encoding) {
-    std::wstring utf16;
-    do {
-        int cw = MultiByteToWideChar(encoding,
-                                    MB_ERR_INVALID_CHARS,
-                                    str.c_str(),
-                                    int(str.size()),
-                                    NULL,
-                                    0);
-        if (cw < 0) {
-            JP_THROW("Unexpected reply from MultiByteToWideChar()");
-        }
-        if (0 == cw) {
-            break;
-        }
-
-        utf16.resize(cw);
-        int cw2 = MultiByteToWideChar(encoding,
-                                    MB_ERR_INVALID_CHARS,
-                                    str.c_str(),
-                                    int(str.size()),
-                                    &*utf16.begin(),
-                                    cw);
-        if (cw != cw2) {
-            JP_THROW("Unexpected reply from MultiByteToWideChar()");
-        }
-    } while(0);
-
-    return utf16;
-}
-} // namespace
-
-std::string toUtf8(const std::wstring& utf16str) {
-    return toMultiByte(utf16str, CP_UTF8);
-}
-
-std::wstring toUtf16(const std::string& utf8str) {
-    return fromMultiByte(utf8str, CP_UTF8);
-}
-
-} // namespace tstrings
-#endif // ifdef TSTRINGS_WITH_WCHAR
--- a/src/jdk.jpackage/windows/native/libjpackage/tstrings.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,426 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef TSTRINGS_H
-#define TSTRINGS_H
-
-#ifdef _MSC_VER
-#   define TSTRINGS_WITH_WCHAR
-#endif
-
-#ifdef TSTRINGS_WITH_WCHAR
-#include <windows.h>
-#include <tchar.h>
-// Want compiler issue C4995 warnings for encounters of deprecated functions.
-#include <strsafe.h>
-#endif
-
-// STL's string header depends on deprecated functions.
-// We don't care about warnings from STL header, so disable them locally.
-#ifdef _MSC_VER
-#   pragma warning(push)
-#   pragma warning(disable:4995)
-#endif
-
-#include <string>
-#include <sstream>
-#include <iostream>
-#include <vector>
-
-#ifdef _MSC_VER
-#   pragma warning(pop)
-#endif
-
-
-#ifndef _T
-#   define _T(x) x
-#endif
-
-
-#ifdef TSTRINGS_WITH_WCHAR
-typedef std::wstring        tstring;
-typedef std::wostringstream tostringstream;
-typedef std::wistringstream tistringstream;
-typedef std::wstringstream  tstringstream;
-typedef std::wistream       tistream;
-typedef std::wostream       tostream;
-typedef std::wiostream      tiostream;
-typedef std::wios           tios;
-#else
-typedef std::string         tstring;
-typedef std::ostringstream  tostringstream;
-typedef std::istringstream  tistringstream;
-typedef std::stringstream   tstringstream;
-typedef std::istream        tistream;
-typedef std::ostream        tostream;
-typedef std::iostream       tiostream;
-typedef std::ios            tios;
-
-typedef const char* LPCTSTR;
-typedef char TCHAR;
-#endif
-
-// frequently used "array of tstrings" type
-typedef std::vector<tstring> tstring_array;
-
-namespace tstrings {
-    tstring unsafe_format(tstring::const_pointer format, ...);
-
-    enum CompareType {CASE_SENSITIVE, IGNORE_CASE};
-    bool equals(const tstring& a, const tstring& b,
-            const CompareType ct=CASE_SENSITIVE);
-    bool startsWith(const tstring &str, const tstring &substr,
-            const CompareType ct=CASE_SENSITIVE);
-    bool endsWith(const tstring &str, const tstring &substr,
-            const CompareType ct=CASE_SENSITIVE);
-
-    enum SplitType {ST_ALL, ST_EXCEPT_EMPTY_STRING};
-    void split(tstring_array &strVector, const tstring &str,
-            const tstring &delimiter, const SplitType st = ST_ALL);
-    inline tstring_array split(const tstring &str, const tstring &delimiter,
-            const SplitType st = ST_ALL) {
-        tstring_array result;
-        split(result, str, delimiter, st);
-        return result;
-    }
-    tstring trim(const tstring& str, const tstring& whitespace = _T(" \t"));
-
-    /**
-     * Writes sequence of values from [b, e) range into string buffer inserting
-     * 'delimiter' after each value except of the last one.
-     * Returns contents of string buffer.
-     */
-    template <class It>
-    tstring join(It b, It e, const tstring& delimiter=tstring()) {
-        tostringstream buf;
-        if (b != e) {
-            for (;;) {
-                buf << *b;
-                if (++b == e) {
-                    break;
-                }
-                buf << delimiter;
-            }
-        }
-        return buf.str();
-    }
-
-    tstring toLower(const tstring& str);
-
-    tstring replace(const tstring &str, const tstring &search,
-            const tstring &replace);
-}
-
-
-namespace tstrings {
-    inline std::string toUtf8(const std::string& utf8str) {
-        return utf8str;
-    }
-
-#ifdef TSTRINGS_WITH_WCHAR
-    // conversion to Utf8
-    std::string toUtf8(const std::wstring& utf16str);
-
-    // conversion to Utf16
-    std::wstring toUtf16(const std::string& utf8str);
-
-    inline std::wstring fromUtf8(const std::string& utf8str) {
-        return toUtf16(utf8str);
-    }
-
-#else
-    inline std::string fromUtf8(const std::string& utf8str) {
-        return utf8str;
-    }
-#endif
-} // namespace tstrings
-
-
-namespace tstrings {
-namespace format_detail {
-
-    template <class T>
-    struct str_arg_value {
-        const tstring value;
-
-        str_arg_value(const std::string& v): value(fromUtf8(v)) {
-        }
-
-#ifdef TSTRINGS_WITH_WCHAR
-        str_arg_value(const std::wstring& v): value(v) {
-        }
-#endif
-
-        tstring::const_pointer operator () () const {
-            return value.c_str();
-        }
-    };
-
-    template <>
-    struct str_arg_value<tstring> {
-        const tstring::const_pointer value;
-
-        str_arg_value(const tstring& v): value(v.c_str()) {
-        }
-
-        str_arg_value(tstring::const_pointer v): value(v) {
-        }
-
-        tstring::const_pointer operator () () const {
-            return value;
-        }
-    };
-
-    inline str_arg_value<std::string> arg(const std::string& v) {
-        return v;
-    }
-
-    inline str_arg_value<std::string> arg(std::string::const_pointer v) {
-        return (v ? v : "(null)");
-    }
-
-#ifdef TSTRINGS_WITH_WCHAR
-    inline str_arg_value<std::wstring> arg(const std::wstring& v) {
-        return v;
-    }
-
-    inline str_arg_value<std::wstring> arg(std::wstring::const_pointer v) {
-        return (v ? v : L"(null)");
-    }
-#else
-    void arg(const std::wstring&);          // Compilation error by design.
-    void arg(std::wstring::const_pointer);  // Compilation error by design.
-#endif
-
-    template <class T>
-    struct arg_value {
-        arg_value(const T v): v(v) {
-        }
-        T operator () () const {
-            return v;
-        }
-    private:
-        const T v;
-    };
-
-    inline arg_value<int> arg(int v) {
-        return v;
-    }
-    inline arg_value<unsigned> arg(unsigned v) {
-        return v;
-    }
-    inline arg_value<long> arg(long v) {
-        return v;
-    }
-    inline arg_value<unsigned long> arg(unsigned long v) {
-        return v;
-    }
-    inline arg_value<long long> arg(long long v) {
-        return v;
-    }
-    inline arg_value<unsigned long long> arg(unsigned long long v) {
-        return v;
-    }
-    inline arg_value<float> arg(float v) {
-        return v;
-    }
-    inline arg_value<double> arg(double v) {
-        return v;
-    }
-    inline arg_value<bool> arg(bool v) {
-        return v;
-    }
-    inline arg_value<const void*> arg(const void* v) {
-        return v;
-    }
-
-} // namespace format_detail
-} // namespace tstrings
-
-
-namespace tstrings {
-    template <class T, class T2, class T3, class T4, class T5, class T6, class T7>
-    inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6, const T7& v7) {
-        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
-                                            format_detail::arg(v2)(),
-                                            format_detail::arg(v3)(),
-                                            format_detail::arg(v4)(),
-                                            format_detail::arg(v5)(),
-                                            format_detail::arg(v6)(),
-                                            format_detail::arg(v7)());
-    }
-
-    template <class T, class T2, class T3, class T4, class T5, class T6>
-    inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5, const T6& v6) {
-        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
-                                            format_detail::arg(v2)(),
-                                            format_detail::arg(v3)(),
-                                            format_detail::arg(v4)(),
-                                            format_detail::arg(v5)(),
-                                            format_detail::arg(v6)());
-    }
-
-    template <class T, class T2, class T3, class T4, class T5>
-    inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4, const T5& v5) {
-        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
-                                            format_detail::arg(v2)(),
-                                            format_detail::arg(v3)(),
-                                            format_detail::arg(v4)(),
-                                            format_detail::arg(v5)());
-    }
-
-    template <class T, class T2, class T3, class T4>
-    inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3, const T4& v4) {
-        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
-                                            format_detail::arg(v2)(),
-                                            format_detail::arg(v3)(),
-                                            format_detail::arg(v4)());
-    }
-
-    template <class T, class T2, class T3>
-    inline tstring format(const tstring& fmt, const T& v, const T2& v2, const T3& v3) {
-        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
-                                            format_detail::arg(v2)(),
-                                            format_detail::arg(v3)());
-    }
-
-    template <class T, class T2>
-    inline tstring format(const tstring& fmt, const T& v, const T2& v2) {
-        return unsafe_format(fmt.c_str(),   format_detail::arg(v)(),
-                                            format_detail::arg(v2)());
-
-    }
-
-    template <class T>
-    inline tstring format(const tstring& fmt, const T& v) {
-        return unsafe_format(fmt.c_str(),   format_detail::arg(v)());
-    }
-} // namespace tstrings
-
-
-namespace tstrings {
-    /**
-     * Buffer that accepts both std::wstring and std::string instances doing
-     * encoding conversions behind the scenes. All std::string-s assumed to be
-     * UTF8-encoded, all std::wstring-s assumed to be UTF16-encoded.
-     */
-    class any {
-    public:
-        any() {
-        }
-
-        any(std::string::const_pointer msg) {
-            data << fromUtf8(msg);
-        }
-
-        any(const std::string& msg) {
-            data << fromUtf8(msg);
-        }
-
-#ifdef TSTRINGS_WITH_WCHAR
-        any(std::wstring::const_pointer msg) {
-            data << msg;
-        }
-
-        any(const std::wstring& msg) {
-            data << msg;
-        }
-
-        any& operator << (const std::wstring& v) {
-            data << v;
-            return *this;
-        }
-
-        // need this specialization instead std::wstring::pointer,
-        // otherwise LPWSTR is handled as abstract pointer (void*)
-        any& operator << (LPWSTR v) {
-            data << (v ? v : L"NULL");
-            return *this;
-        }
-
-        // need this specialization instead std::wstring::const_pointer,
-        // otherwise LPCWSTR is handled as abstract pointer (const void*)
-        any& operator << (LPCWSTR v) {
-            data << (v ? v : L"NULL");
-            return *this;
-        }
-
-        std::wstring wstr() const {
-            return data.str();
-        }
-#endif
-
-        template <class T>
-        any& operator << (T v) {
-            data << v;
-            return *this;
-        }
-
-        any& operator << (tostream& (*pf)(tostream&)) {
-            data << pf;
-            return *this;
-        }
-
-        any& operator << (tios& (*pf)(tios&)) {
-            data << pf;
-            return *this;
-        }
-
-        any& operator << (std::ios_base& (*pf)(std::ios_base&)) {
-            data << pf;
-            return *this;
-        }
-
-        std::string str() const {
-            return toUtf8(data.str());
-        }
-
-        tstring tstr() const {
-            return data.str();
-        }
-
-    private:
-        tostringstream data;
-    };
-
-    inline tstring to_tstring(const any& val) {
-        return val.tstr();
-    }
-} // namespace tstrings
-
-
-inline std::ostream& operator << (std::ostream& os, const tstrings::any& buf) {
-    os << buf.str();
-    return os;
-}
-
-#ifdef TSTRINGS_WITH_WCHAR
-inline std::wostream& operator << (std::wostream& os, const tstrings::any& buf) {
-    os << buf.wstr();
-    return os;
-}
-#endif
-
-#endif //TSTRINGS_H
--- a/src/jdk.jpackage/windows/native/libwixhelper/libwixhelper.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include <Windows.h>
-#include <msiquery.h>
-#include <shlwapi.h>
-
-extern "C" {
-
-#ifdef JP_EXPORT_FUNCTION
-#error Unexpected JP_EXPORT_FUNCTION define
-#endif
-#define JP_EXPORT_FUNCTION comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
-
-    BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason,
-            LPVOID lpvReserved) {
-        return TRUE;
-    }
-
-    BOOL DirectoryExist(TCHAR *szValue) {
-        DWORD attr = GetFileAttributes(szValue);
-        if (attr == INVALID_FILE_ATTRIBUTES) {
-            return FALSE;
-        }
-
-        if (attr & FILE_ATTRIBUTE_DIRECTORY) {
-            return TRUE;
-        }
-
-        return FALSE;
-    }
-
-    UINT __stdcall CheckInstallDir(MSIHANDLE hInstall) {
-        #pragma JP_EXPORT_FUNCTION
-
-        TCHAR *szValue = NULL;
-        DWORD cchSize = 0;
-
-        UINT result = MsiGetProperty(hInstall, TEXT("INSTALLDIR"),
-                TEXT(""), &cchSize);
-        if (result == ERROR_MORE_DATA) {
-            cchSize = cchSize + 1; // NULL termination
-            szValue = new TCHAR[cchSize];
-            if (szValue) {
-                result = MsiGetProperty(hInstall, TEXT("INSTALLDIR"),
-                        szValue, &cchSize);
-            } else {
-                return ERROR_INSTALL_FAILURE;
-            }
-        }
-
-        if (result != ERROR_SUCCESS) {
-            delete [] szValue;
-            return ERROR_INSTALL_FAILURE;
-        }
-
-        if (DirectoryExist(szValue)) {
-            if (PathIsDirectoryEmpty(szValue)) {
-                MsiSetProperty(hInstall, TEXT("INSTALLDIR_VALID"), TEXT("1"));
-            } else {
-                MsiSetProperty(hInstall, TEXT("INSTALLDIR_VALID"), TEXT("0"));
-            }
-        } else {
-            MsiSetProperty(hInstall, TEXT("INSTALLDIR_VALID"), TEXT("1"));
-        }
-
-        delete [] szValue;
-
-        return ERROR_SUCCESS;
-    }
-}
--- a/src/jdk.jpackage/windows/native/msiwrapper/Executor.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include <algorithm>
-#include "Executor.h"
-#include "Log.h"
-#include "WinErrorHandling.h"
-
-
-namespace {
-
-void escapeArg(std::wstring& str) {
-    if (str.empty()) {
-        return;
-    }
-
-    if (str.front() == L'\"' && str.back() == L'\"' && str.size() > 1) {
-        return;
-    }
-
-    if (str.find_first_of(L" \t") != std::wstring::npos) {
-        str = L'"' + str + L'"';
-    }
-}
-
-} // namespace
-
-
-std::wstring Executor::args() const {
-    tstring_array tmpArgs;
-    // argv[0] is the module name.
-    tmpArgs.push_back(appPath);
-    tmpArgs.insert(tmpArgs.end(), argsArray.begin(), argsArray.end());
-
-    std::for_each(tmpArgs.begin(), tmpArgs.end(), escapeArg);
-    return tstrings::join(tmpArgs.begin(), tmpArgs.end(), _T(" "));
-}
-
-
-int Executor::execAndWaitForExit() const {
-    UniqueHandle h = startProcess();
-
-    const DWORD res = ::WaitForSingleObject(h.get(), INFINITE);
-    if (WAIT_FAILED ==  res) {
-        JP_THROW(SysError("WaitForSingleObject() failed", WaitForSingleObject));
-    }
-
-    DWORD exitCode = 0;
-    if (!GetExitCodeProcess(h.get(), &exitCode)) {
-        // Error reading process's exit code.
-        JP_THROW(SysError("GetExitCodeProcess() failed", GetExitCodeProcess));
-    }
-
-    const DWORD processId = GetProcessId(h.get());
-    if (!processId) {
-        JP_THROW(SysError("GetProcessId() failed.", GetProcessId));
-    }
-
-    LOG_TRACE(tstrings::any() << "Process with PID=" << processId
-                                << " terminated. Exit code=" << exitCode);
-
-    return static_cast<int>(exitCode);
-}
-
-
-UniqueHandle Executor::startProcess() const {
-    const std::wstring argsStr = args();
-
-    std::vector<TCHAR> argsBuffer(argsStr.begin(), argsStr.end());
-    argsBuffer.push_back(0); // terminating '\0'
-
-    STARTUPINFO startupInfo;
-    ZeroMemory(&startupInfo, sizeof(startupInfo));
-    startupInfo.cb = sizeof(startupInfo);
-
-    PROCESS_INFORMATION processInfo;
-    ZeroMemory(&processInfo, sizeof(processInfo));
-
-    DWORD creationFlags = 0;
-
-    if (!theVisible) {
-        // For GUI applications.
-        startupInfo.dwFlags |= STARTF_USESHOWWINDOW;
-        startupInfo.wShowWindow = SW_HIDE;
-
-        // For console applications.
-        creationFlags |= CREATE_NO_WINDOW;
-    }
-
-    tstrings::any msg;
-    msg << "CreateProcess(" << appPath << ", " << argsStr << ")";
-
-    if (!CreateProcess(appPath.c_str(), argsBuffer.data(), NULL, NULL, FALSE,
-                    creationFlags, NULL, NULL, &startupInfo, &processInfo)) {
-        msg << " failed";
-        JP_THROW(SysError(msg, CreateProcess));
-    }
-
-    msg << " succeeded; PID=" << processInfo.dwProcessId;
-    LOG_TRACE(msg);
-
-    // Close unneeded handles immediately.
-    UniqueHandle(processInfo.hThread);
-
-    // Return process handle.
-    return UniqueHandle(processInfo.hProcess);
-}
--- a/src/jdk.jpackage/windows/native/msiwrapper/Executor.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef EXECUTOR_H
-#define EXECUTOR_H
-
-#include "tstrings.h"
-#include "UniqueHandle.h"
-
-
-class Executor {
-public:
-    explicit Executor(const std::wstring& appPath=std::wstring()) {
-        app(appPath).visible(false);
-    }
-
-    /**
-     * Returns command line configured with arg() calls so far.
-     */
-    std::wstring args() const;
-
-    /**
-     * Set path to application to execute.
-     */
-    Executor& app(const std::wstring& v) {
-        appPath = v;
-        return *this;
-    }
-
-    /**
-     * Adds another command line argument.
-     */
-    Executor& arg(const std::wstring& v) {
-        argsArray.push_back(v);
-        return *this;
-    }
-
-    /**
-     * Controls if application window should be visible.
-     */
-    Executor& visible(bool v) {
-        theVisible = v;
-        return *this;
-    }
-
-    /**
-     * Starts application process and blocks waiting when the started
-     * process terminates.
-     * Returns process exit code.
-     * Throws exception if process start failed.
-     */
-    int execAndWaitForExit() const;
-
-private:
-    UniqueHandle startProcess() const;
-
-    bool theVisible;
-    tstring_array argsArray;
-    std::wstring appPath;
-};
-
-#endif // #ifndef EXECUTOR_H
--- a/src/jdk.jpackage/windows/native/msiwrapper/MsiWrapper.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#include <algorithm>
-#include <windows.h>
-
-#include "SysInfo.h"
-#include "FileUtils.h"
-#include "Executor.h"
-#include "Resources.h"
-#include "WinErrorHandling.h"
-
-
-int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR lpCmdLine, int nShowCmd)
-{
-    JP_TRY;
-
-    // Create temporary directory where to extract msi file.
-    const auto tempMsiDir = FileUtils::createTempDirectory();
-
-    // Schedule temporary directory for deletion.
-    FileUtils::Deleter cleaner;
-    cleaner.appendRecursiveDirectory(tempMsiDir);
-
-    const auto msiPath = FileUtils::mkpath() << tempMsiDir << L"main.msi";
-
-    // Extract msi file.
-    Resource(L"msi", RT_RCDATA).saveToFile(msiPath);
-
-    // Setup executor to run msiexec
-    Executor msiExecutor(SysInfo::getWIPath());
-    msiExecutor.arg(L"/i").arg(msiPath);
-    const auto args = SysInfo::getCommandArgs();
-    std::for_each(args.begin(), args.end(),
-            [&msiExecutor] (const tstring& arg) {
-        msiExecutor.arg(arg);
-    });
-
-    // Install msi file.
-    return msiExecutor.execAndWaitForExit();
-
-    JP_CATCH_ALL;
-
-    return -1;
-}
--- a/src/jdk.jpackage/windows/native/msiwrapper/Resources.cpp	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#include "Resources.h"
-#include "FileUtils.h"
-#include "WinErrorHandling.h"
-
-#include <fstream>
-
-
-Resource::Resource(LPCTSTR name, LPCTSTR type, HINSTANCE module) {
-    init(name, type, module);
-}
-
-Resource::Resource(UINT id, LPCTSTR type, HINSTANCE module) {
-    init(MAKEINTRESOURCE(id), type, module);
-}
-
-void Resource::init(LPCTSTR name, LPCTSTR type, HINSTANCE module) {
-    if (IS_INTRESOURCE(name)) {
-        std::wostringstream printer;
-        printer << L"#" << reinterpret_cast<size_t>(name);
-        nameStr = printer.str();
-        namePtr = name;
-    } else {
-        nameStr = name;
-        namePtr = nameStr.c_str();
-    }
-    if (IS_INTRESOURCE(type)) {
-        std::wostringstream printer;
-        printer << L"#" << reinterpret_cast<size_t>(name);
-        typeStr = printer.str();
-        typePtr = type;
-    } else {
-        typeStr = type;
-        typePtr = typeStr.c_str();
-    }
-    instance = module;
-}
-
-std::string Resource::getErrMsg(const std::string &descr) const {
-    return (tstrings::any() << descr << " (name='" << nameStr <<
-            "', type='" << typeStr << "')").str();
-}
-
-HRSRC Resource::findResource() const {
-    LPCTSTR id = namePtr;
-    // string resources are stored in blocks (stringtables)
-    // id of the resource is (stringId / 16 + 1)
-    if (typePtr == RT_STRING) {
-        id = MAKEINTRESOURCE(UINT(size_t(id) / 16 + 1));
-    }
-    return FindResource(instance, id, typePtr);
-}
-
-LPVOID Resource::getPtr(DWORD &size) const
-{
-    // LoadString returns the same result if value is zero-length or
-    // if if the value does not exists,
-    // so wee need to ensure the stringtable exists
-    HRSRC resInfo = findResource();
-    if (resInfo == NULL) {
-        JP_THROW(SysError(getErrMsg("cannot find resource"), FindResource));
-    }
-
-    HGLOBAL res = LoadResource(instance, resInfo);
-    if (res == NULL) {
-        JP_THROW(SysError(getErrMsg("cannot load resource"), LoadResource));
-    }
-
-    LPVOID ptr = LockResource(res);
-    if (res == NULL) {
-        JP_THROW(SysError(getErrMsg("cannot lock resource"), LockResource));
-    }
-
-    if (typePtr == RT_STRING) {
-        // string resources are stored in stringtables and
-        // need special handling
-        // The simplest way (while we don't need handle resource locale)
-        // is LoadString
-        // But this adds dependency on user32.dll,
-        // so implement custom string extraction
-
-        // number in the block (namePtr is an integer)
-        size_t num = size_t(namePtr) & 0xf;
-        LPWSTR strPtr = (LPWSTR)ptr;
-        for (size_t i = 0; i < num; i++) {
-            // 1st symbol contains string length
-            strPtr += DWORD(*strPtr) + 1;
-        }
-        // *strPtr contains string length, string value starts at strPtr+1
-        size = DWORD(*strPtr) * sizeof(wchar_t);
-        ptr = strPtr+1;
-    } else {
-        size = SizeofResource(instance, resInfo);
-    }
-
-    return ptr;
-}
-
-bool Resource::available() const {
-    return NULL != findResource();
-}
-
-unsigned Resource::size() const {
-    DWORD size = 0;
-    getPtr(size);
-    return size;
-}
-
-LPCVOID Resource::rawData() const {
-    DWORD size = 0;
-    return getPtr(size);
-}
-
-void Resource::saveToFile(const std::wstring &filePath) const {
-    DWORD size = 0;
-    const char *resPtr = (const char *)getPtr(size);
-
-    FileUtils::FileWriter(filePath).write(resPtr, size).finalize();
-}
-
-Resource::ByteArray Resource::binary() const {
-    DWORD size = 0;
-    LPBYTE resPtr = (LPBYTE)getPtr(size);
-    return ByteArray(resPtr, resPtr+size);
-}
--- a/src/jdk.jpackage/windows/native/msiwrapper/Resources.h	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-
-#ifndef RESOURCES_H
-#define RESOURCES_H
-
-#include "WinSysInfo.h"
-
-
-/**
- * Classes for resource loading.
- * Common use cases:
- *  - check if resource is available and save it to file:
- *      Resource res(_T("MyResource"), _T("CustomResourceType"));
- *      if (res.available()) {
- *          res.saveToFile(_T("c:\\temp\\my_resource.bin"));
- *      }
- */
-
-class Resource {
-public:
-    // name and type can be specified by string id,
-    // by integer id (RT_* constants or MAKEINTRESOURCE)
-    Resource(LPCWSTR name, LPCWSTR type,
-            HINSTANCE module = SysInfo::getCurrentModuleHandle());
-    Resource(UINT id, LPCWSTR type,
-            HINSTANCE module = SysInfo::getCurrentModuleHandle());
-
-    bool available() const;
-
-    // all this methods throw exception if the resource is not available
-    unsigned size() const;
-    // gets raw pointer to the resource data
-    LPCVOID rawData() const;
-
-    // save the resource to a file
-    void saveToFile(const std::wstring &filePath) const;
-
-    typedef std::vector<BYTE> ByteArray;
-    // returns the resource as byte array
-    ByteArray binary() const;
-
-private:
-    std::wstring nameStr;
-    LPCWSTR namePtr;    // can be integer value or point to nameStr.c_str()
-    std::wstring typeStr;
-    LPCWSTR typePtr;    // can be integer value or point to nameStr.c_str()
-    HINSTANCE instance;
-
-    void init(LPCWSTR name, LPCWSTR type, HINSTANCE module);
-
-    // generates error message
-    std::string getErrMsg(const std::string &descr) const;
-    HRSRC findResource() const;
-    LPVOID getPtr(DWORD &size) const;
-
-private:
-    // disable copying
-    Resource(const Resource&);
-    Resource& operator = (const Resource&);
-};
-
-#endif // RESOURCES_H
--- a/test/jdk/tools/jpackage/helpers/JPackageHelper.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/helpers/JPackageHelper.java	Fri Nov 08 14:53:03 2019 -0500
@@ -38,6 +38,7 @@
 import java.util.stream.Stream;
 
 import java.util.spi.ToolProvider;
+import jdk.incubator.jpackage.ToolProviderFactory;
 
 public class JPackageHelper {
 
@@ -113,7 +114,7 @@
     }
 
     static final ToolProvider JPACKAGE_TOOL =
-            ToolProvider.findFirst("jpackage").orElseThrow(
+            ToolProviderFactory.findFirst("jpackage").orElseThrow(
             () -> new RuntimeException("jpackage tool not found"));
 
     public static int execute(File out, String... command) throws Exception {
@@ -572,7 +573,7 @@
 
         return Stream.of(output.split("\\R"))
                 .filter(str -> !str.startsWith("Picked up"))
-                .filter(str -> !str.startsWith("WARNING: Using experimental"))
+                .filter(str -> !str.startsWith("WARNING: Using incubator"))
                 .filter(str -> !str.startsWith("hello: "))
                 .collect(Collectors.toList()).toArray(String[]::new);
     }
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java	Fri Nov 08 14:53:03 2019 -0500
@@ -35,7 +35,7 @@
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-import jdk.jpackage.internal.ApplicationLayout;
+import jdk.incubator.jpackage.internal.ApplicationLayout;
 import jdk.jpackage.test.Functional.ThrowingConsumer;
 import jdk.jpackage.test.Functional.ThrowingFunction;
 
@@ -686,7 +686,7 @@
     }
 
     public static Stream<String> filterOutput(Stream<String> jpackageOutput) {
-        // Skip "WARNING: Using experimental tool jpackage" first line of output
+        // Skip "WARNING: Using incubator ..." first line of output
         return jpackageOutput.skip(1);
     }
 
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JavaTool.java	Fri Nov 08 14:53:03 2019 -0500
@@ -27,6 +27,7 @@
 
 import java.nio.file.Path;
 import java.util.spi.ToolProvider;
+import jdk.incubator.jpackage.ToolProviderFactory;
 
 public enum JavaTool {
     JAVA("java"), JAVAC("javac"), JPACKAGE("jpackage"), JAR("jar"), JLINK("jlink");
@@ -46,7 +47,12 @@
     }
 
     public ToolProvider asToolProvider() {
-        return ToolProvider.findFirst(name).orElse(null);
+        if (this == JPACKAGE) {
+            return ToolProviderFactory.findFirst("jpackage").orElseThrow(
+                    () -> new RuntimeException("jpackage tool not found"));
+        } else {
+            return ToolProvider.findFirst(name).orElse(null);
+        }
     }
 
     Path relativePathInJavaHome() {
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -35,7 +35,7 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import jdk.jpackage.test.Functional.ThrowingConsumer;
-import jdk.jpackage.internal.AppImageFile;
+import jdk.incubator.jpackage.internal.AppImageFile;
 import static jdk.jpackage.test.PackageType.*;
 
 /**
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java	Fri Nov 08 14:53:03 2019 -0500
@@ -35,15 +35,15 @@
  */
 public enum PackageType {
     WIN_MSI(".msi",
-            TKit.isWindows() ? "jdk.jpackage.internal.WinMsiBundler" : null),
+            TKit.isWindows() ? "jdk.incubator.jpackage.internal.WinMsiBundler" : null),
     WIN_EXE(".exe",
-            TKit.isWindows() ? "jdk.jpackage.internal.WinMsiBundler" : null),
+            TKit.isWindows() ? "jdk.incubator.jpackage.internal.WinMsiBundler" : null),
     LINUX_DEB(".deb",
-            TKit.isLinux() ? "jdk.jpackage.internal.LinuxDebBundler" : null),
+            TKit.isLinux() ? "jdk.incubator.jpackage.internal.LinuxDebBundler" : null),
     LINUX_RPM(".rpm",
-            TKit.isLinux() ? "jdk.jpackage.internal.LinuxRpmBundler" : null),
-    MAC_DMG(".dmg", TKit.isOSX() ? "jdk.jpackage.internal.MacDmgBundler" : null),
-    MAC_PKG(".pkg", TKit.isOSX() ? "jdk.jpackage.internal.MacPkgBundler" : null),
+            TKit.isLinux() ? "jdk.incubator.jpackage.internal.LinuxRpmBundler" : null),
+    MAC_DMG(".dmg", TKit.isOSX() ? "jdk.incubator.jpackage.internal.MacDmgBundler" : null),
+    MAC_PKG(".pkg", TKit.isOSX() ? "jdk.incubator.jpackage.internal.MacPkgBundler" : null),
     IMAGE("app-image", null, null);
 
     PackageType(String packageName, String bundleSuffix, String bundlerClass) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/AppImageFileTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.LinkedHashMap;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+
+public class AppImageFileTest {
+
+    @Rule
+    public final TemporaryFolder tempFolder = new TemporaryFolder();
+
+    @Test
+    public void testIdentity() throws IOException {
+        Map<String, ? super Object> params = new LinkedHashMap<>();
+        params.put("name", "Foo");
+        params.put("app-version", "2.3");
+        params.put("description", "Duck is the King");
+        AppImageFile aif = create(params);
+
+        Assert.assertEquals("Foo", aif.getLauncherName());
+    }
+
+    @Test
+    public void testInvalidCommandLine() throws IOException {
+        // Just make sure AppImageFile will tolerate jpackage params that would
+        // never create app image at both load/save phases.
+        // People would edit this file just because they can.
+        // We should be ready to handle curious minds.
+        Map<String, ? super Object> params = new LinkedHashMap<>();
+        params.put("invalidParamName", "randomStringValue");
+        create(params);
+
+        params = new LinkedHashMap<>();
+        params.put("name", "foo");
+        params.put("app-version", "");
+        create(params);
+    }
+
+    @Test
+    public void testInavlidXml() throws IOException {
+        assertInvalid(createFromXml("<foo/>"));
+        assertInvalid(createFromXml("<jpackage-state/>"));
+        assertInvalid(createFromXml(
+                "<jpackage-state>",
+                    "<main-launcher></main-launcher>",
+                "</jpackage-state>"));
+        assertInvalid(createFromXml(
+                "<jpackage-state>",
+                    "<launcher>A</launcher>",
+                    "<launcher>B</launcher>",
+                "</jpackage-state>"));
+    }
+
+    @Test
+    public void testValidXml() throws IOException {
+        Assert.assertEquals("Foo", (createFromXml(
+                "<jpackage-state>",
+                    "<main-launcher>Foo</main-launcher>",
+                "</jpackage-state>")).getLauncherName());
+
+        Assert.assertEquals("Boo", (createFromXml(
+                "<jpackage-state>",
+                    "<main-launcher>Boo</main-launcher>",
+                    "<main-launcher>Bar</main-launcher>",
+                "</jpackage-state>")).getLauncherName());
+
+        var file = createFromXml(
+                "<jpackage-state>",
+                    "<main-launcher>Foo</main-launcher>",
+                    "<launcher></launcher>",
+                "</jpackage-state>");
+        Assert.assertEquals("Foo", file.getLauncherName());
+        Assert.assertArrayEquals(new String[0],
+                file.getAddLauncherNames().toArray(String[]::new));
+    }
+
+    @Test
+    public void testMainLauncherName() throws IOException {
+        Map<String, ? super Object> params = new LinkedHashMap<>();
+        params.put("name", "Foo");
+        params.put("description", "Duck App Description");
+        AppImageFile aif = create(params);
+
+        Assert.assertEquals("Foo", aif.getLauncherName());
+    }
+
+    @Test
+    public void testAddLauncherNames() throws IOException {
+        Map<String, ? super Object> params = new LinkedHashMap<>();
+        List<Map<String, ? super Object>> launchersAsMap = new ArrayList<>();
+
+        Map<String, ? super Object> addLauncher2Params = new LinkedHashMap();
+        addLauncher2Params.put("name", "Launcher2Name");
+        launchersAsMap.add(addLauncher2Params);
+
+        Map<String, ? super Object> addLauncher3Params = new LinkedHashMap();
+        addLauncher3Params.put("name", "Launcher3Name");
+        launchersAsMap.add(addLauncher3Params);
+
+        params.put("name", "Duke App");
+        params.put("description", "Duke App Description");
+        params.put("add-launcher", launchersAsMap);
+        AppImageFile aif = create(params);
+
+        List<String> addLauncherNames = aif.getAddLauncherNames();
+        Assert.assertEquals(2, addLauncherNames.size());
+        Assert.assertTrue(addLauncherNames.contains("Launcher2Name"));
+        Assert.assertTrue(addLauncherNames.contains("Launcher3Name"));
+
+    }
+
+    private AppImageFile create(Map<String, Object> params) throws IOException {
+        AppImageFile.save(tempFolder.getRoot().toPath(), params);
+        return AppImageFile.load(tempFolder.getRoot().toPath());
+    }
+
+    private void assertInvalid(AppImageFile file) {
+        Assert.assertNull(file.getLauncherName());
+        Assert.assertNull(file.getAddLauncherNames());
+    }
+
+    private AppImageFile createFromXml(String... xmlData) throws IOException {
+        Path directory = tempFolder.getRoot().toPath();
+        Path path = AppImageFile.getPathInAppImage(directory);
+        path.toFile().mkdirs();
+        Files.delete(path);
+
+        ArrayList<String> data = new ArrayList();
+        data.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>");
+        data.addAll(List.of(xmlData));
+
+        Files.write(path, data, StandardOpenOption.CREATE,
+                    StandardOpenOption.TRUNCATE_EXISTING);
+
+        AppImageFile image = AppImageFile.load(directory);
+        return image;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/ApplicationLayoutTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.junit.Test;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+import static org.junit.Assert.*;
+
+
+public class ApplicationLayoutTest {
+
+    @Rule
+    public final TemporaryFolder tempFolder = new TemporaryFolder();
+
+    private void fillLinuxAppImage() throws IOException {
+        appImage = tempFolder.newFolder("Foo").toPath();
+
+        Path base = appImage.getFileName();
+
+        tempFolder.newFolder(base.toString(), "bin");
+        tempFolder.newFolder(base.toString(), "lib", "app", "mods");
+        tempFolder.newFolder(base.toString(), "lib", "runtime", "bin");
+        tempFolder.newFile(base.resolve("bin/Foo").toString());
+        tempFolder.newFile(base.resolve("lib/app/Foo.cfg").toString());
+        tempFolder.newFile(base.resolve("lib/app/hello.jar").toString());
+        tempFolder.newFile(base.resolve("lib/Foo.png").toString());
+        tempFolder.newFile(base.resolve("lib/libapplauncher.so").toString());
+        tempFolder.newFile(base.resolve("lib/runtime/bin/java").toString());
+    }
+
+    @Test
+    public void testLinux() throws IOException {
+        fillLinuxAppImage();
+        testApplicationLayout(ApplicationLayout.linuxAppImage());
+    }
+
+    private void testApplicationLayout(ApplicationLayout layout) throws IOException {
+        ApplicationLayout srcLayout = layout.resolveAt(appImage);
+        assertApplicationLayout(srcLayout);
+
+        ApplicationLayout dstLayout = layout.resolveAt(
+                appImage.getParent().resolve(
+                        "Copy" + appImage.getFileName().toString()));
+        srcLayout.move(dstLayout);
+        Files.deleteIfExists(appImage);
+        assertApplicationLayout(dstLayout);
+
+        dstLayout.copy(srcLayout);
+        assertApplicationLayout(srcLayout);
+        assertApplicationLayout(dstLayout);
+    }
+
+    private void assertApplicationLayout(ApplicationLayout layout) throws IOException {
+        assertTrue(Files.isRegularFile(layout.appDirectory().resolve("Foo.cfg")));
+        assertTrue(Files.isRegularFile(layout.appDirectory().resolve("hello.jar")));
+        assertTrue(Files.isDirectory(layout.appModsDirectory()));
+        assertTrue(Files.isRegularFile(layout.launchersDirectory().resolve("Foo")));
+        assertTrue(Files.isRegularFile(layout.destktopIntegrationDirectory().resolve("Foo.png")));
+        assertTrue(Files.isRegularFile(layout.dllDirectory().resolve("libapplauncher.so")));
+        assertTrue(Files.isRegularFile(layout.runtimeDirectory().resolve("bin/java")));
+    }
+
+    private Path appImage;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/CompareDottedVersionTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+package jdk.incubator.jpackage.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import static org.junit.Assert.*;
+
+@RunWith(Parameterized.class)
+public class CompareDottedVersionTest {
+
+    public CompareDottedVersionTest(boolean greedy, String version1,
+            String version2, int result) {
+        this.version1 = version1;
+        this.version2 = version2;
+        this.expectedResult = result;
+
+        if (greedy) {
+            createTestee = DottedVersion::greedy;
+        } else {
+            createTestee = DottedVersion::lazy;
+        }
+    }
+
+    @Parameters
+    public static List<Object[]> data() {
+        List<Object[]> data = new ArrayList<>();
+        for (var greedy : List.of(true, false)) {
+            data.addAll(List.of(new Object[][] {
+                { greedy, "00.0.0", "0", 0 },
+                { greedy, "0.035", "0.0035", 0 },
+                { greedy, "1", "1", 0 },
+                { greedy, "2", "2.0", 0 },
+                { greedy, "2.00", "2.0", 0 },
+                { greedy, "1.2.3.4", "1.2.3.4.5", -1 },
+                { greedy, "34", "33", 1 },
+                { greedy, "34.0.78", "34.1.78", -1 }
+            }));
+        }
+
+        data.addAll(List.of(new Object[][] {
+            { false, "", "1", -1 },
+            { false, "1.2.4-R4", "1.2.4-R5", 0 },
+            { false, "1.2.4.-R4", "1.2.4.R5", 0 },
+            { false, "7+1", "7+4", 0 },
+            { false, "2+14", "2-14", 0 },
+            { false, "23.4.RC4", "23.3.RC10", 1 },
+            { false, "77.0", "77.99999999999999999999999999999999999999999999999", 0 },
+        }));
+
+        return data;
+    }
+
+    @Test
+    public void testIt() {
+        int actualResult = compare(version1, version2);
+        assertEquals(expectedResult, actualResult);
+
+        int actualNegateResult = compare(version2, version1);
+        assertEquals(actualResult, -1 * actualNegateResult);
+    }
+
+    private int compare(String x, String y) {
+        int result = createTestee.apply(x).compareTo(y);
+
+        if (result < 0) {
+            return -1;
+        }
+
+        if (result > 0) {
+            return 1;
+        }
+
+        return 0;
+    }
+
+    private final String version1;
+    private final String version2;
+    private final int expectedResult;
+    private final Function<String, DottedVersion> createTestee;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/DeployParamsTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018, 2019, 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.
+ */
+package jdk.incubator.jpackage.internal;
+
+import java.io.File;
+import java.io.IOException;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.junit.Rule;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * Test for JDK-8211285
+ */
+public class DeployParamsTest {
+
+    @Rule
+    public final TemporaryFolder tempFolder = new TemporaryFolder();
+
+    @Rule
+    public final ExpectedException thrown = ExpectedException.none();
+
+    @Before
+    public void setUp() throws IOException {
+        testRoot = tempFolder.newFolder();
+    }
+
+    @Test
+    public void testValidAppName() throws PackagerException {
+        initParamsAppName();
+
+        setAppNameAndValidate("Test");
+
+        setAppNameAndValidate("Test Name");
+
+        setAppNameAndValidate("Test - Name !!!");
+    }
+
+    @Test
+    public void testInvalidAppName() throws PackagerException {
+        initForInvalidAppNamePackagerException();
+        initParamsAppName();
+        setAppNameAndValidate("Test\nName");
+    }
+
+    @Test
+    public void testInvalidAppName2() throws PackagerException {
+        initForInvalidAppNamePackagerException();
+        initParamsAppName();
+        setAppNameAndValidate("Test\rName");
+    }
+
+    @Test
+    public void testInvalidAppName3() throws PackagerException {
+        initForInvalidAppNamePackagerException();
+        initParamsAppName();
+        setAppNameAndValidate("TestName\\");
+    }
+
+    @Test
+    public void testInvalidAppName4() throws PackagerException {
+        initForInvalidAppNamePackagerException();
+        initParamsAppName();
+        setAppNameAndValidate("Test \" Name");
+    }
+
+    private void initForInvalidAppNamePackagerException() {
+        thrown.expect(PackagerException.class);
+
+        String msg = "Error: Invalid Application name";
+
+        // Unfortunately org.hamcrest.core.StringStartsWith is not available
+        // with older junit, DIY
+
+        // thrown.expectMessage(startsWith("Error: Invalid Application name"));
+        thrown.expectMessage(new BaseMatcher() {
+            @Override
+            @SuppressWarnings("unchecked")
+            public boolean matches(Object o) {
+                if (o instanceof String) {
+                    return ((String) o).startsWith(msg);
+                }
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description d) {
+                d.appendText(msg);
+            }
+        });
+    }
+
+    // Returns deploy params initialized to pass all validation, except for
+    // app name
+    private void initParamsAppName() {
+        params = new DeployParams();
+
+        params.setOutput(testRoot);
+        params.addResource(testRoot, new File(testRoot, "test.jar"));
+        params.addBundleArgument(Arguments.CLIOptions.APPCLASS.getId(),
+                "TestClass");
+        params.addBundleArgument(Arguments.CLIOptions.MAIN_JAR.getId(),
+                "test.jar");
+        params.addBundleArgument(Arguments.CLIOptions.INPUT.getId(), "input");
+    }
+
+    private void setAppNameAndValidate(String appName) throws PackagerException {
+        params.addBundleArgument(Arguments.CLIOptions.NAME.getId(), appName);
+        params.validate();
+    }
+
+    private File testRoot = null;
+    private DeployParams params;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/DottedVersionTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+package jdk.incubator.jpackage.internal;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import static org.junit.Assert.*;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DottedVersionTest {
+
+    public DottedVersionTest(boolean greedy) {
+        this.greedy = greedy;
+        if (greedy) {
+            createTestee = DottedVersion::greedy;
+        } else {
+            createTestee = DottedVersion::lazy;
+        }
+    }
+
+    @Parameterized.Parameters
+    public static List<Object[]> data() {
+        return List.of(new Object[] { true }, new Object[] { false });
+    }
+
+    @Rule
+    public ExpectedException exceptionRule = ExpectedException.none();
+
+    @Test
+    public void testValid() {
+        final List<String> validStrings = List.of(
+            "1.0",
+            "1",
+            "2.234.045",
+            "2.234.0",
+            "0",
+            "0.1"
+        );
+
+        final List<String> validLazyStrings;
+        if (greedy) {
+            validLazyStrings = Collections.emptyList();
+        } else {
+            validLazyStrings = List.of(
+                "1.-1",
+                "5.",
+                "4.2.",
+                "3..2",
+                "2.a",
+                "0a",
+                ".",
+                " ",
+                " 1",
+                "1. 2",
+                "+1",
+                "-1",
+                "-0",
+                "1234567890123456789012345678901234567890"
+            );
+        }
+
+        Stream.concat(validStrings.stream(), validLazyStrings.stream())
+        .forEach(value -> {
+            DottedVersion version = createTestee.apply(value);
+            assertEquals(version.toString(), value);
+        });
+    }
+
+    @Test
+    public void testNull() {
+        exceptionRule.expect(NullPointerException.class);
+        createTestee.apply(null);
+    }
+
+    @Test
+    public void testEmpty() {
+        if (greedy) {
+            exceptionRule.expect(IllegalArgumentException.class);
+            exceptionRule.expectMessage("Version may not be empty string");
+            createTestee.apply("");
+        } else {
+            assertTrue(0 == createTestee.apply("").compareTo(""));
+            assertTrue(0 == createTestee.apply("").compareTo("0"));
+        }
+    }
+
+    private final boolean greedy;
+    private final Function<String, DottedVersion> createTestee;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/InvalidDottedVersionTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+package jdk.incubator.jpackage.internal;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class InvalidDottedVersionTest {
+
+    public InvalidDottedVersionTest(String version) {
+        this.version = version;
+    }
+
+    @Parameters
+    public static List<Object[]> data() {
+        return Stream.of(
+            "1.-1",
+            "5.",
+            "4.2.",
+            "3..2",
+            "2.a",
+            "0a",
+            ".",
+            " ",
+            " 1",
+            "1. 2",
+            "+1",
+            "-1",
+            "-0",
+            "1234567890123456789012345678901234567890"
+        ).map(version -> new Object[] { version }).collect(Collectors.toList());
+    }
+
+    @Rule
+    public ExpectedException exceptionRule = ExpectedException.none();
+
+    @Test
+    public void testIt() {
+        exceptionRule.expect(IllegalArgumentException.class);
+        new DottedVersion(version);
+    }
+
+    private final String version;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/OverridableResourceTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import jdk.incubator.jpackage.internal.resources.ResourceLocator;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.*;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class OverridableResourceTest {
+
+    @Rule
+    public final TemporaryFolder tempFolder = new TemporaryFolder();
+
+    @Test
+    public void testDefault() throws IOException {
+        byte[] actualBytes = saveToFile(new OverridableResource(DEFAULT_NAME));
+
+        try (InputStream is = ResourceLocator.class.getResourceAsStream(
+                DEFAULT_NAME)) {
+            assertArrayEquals(is.readAllBytes(), actualBytes);
+        }
+    }
+
+    @Test
+    public void testDefaultWithSubstitution() throws IOException {
+        OverridableResource resource = new OverridableResource(DEFAULT_NAME);
+
+        List<String> linesBeforeSubstitution = convertToStringList(saveToFile(
+                resource));
+
+        if (SUBSTITUTION_DATA.size() != 1) {
+            // Test setup issue
+            throw new IllegalArgumentException(
+                    "Substitution map should contain only a single entry");
+        }
+
+        resource.setSubstitutionData(SUBSTITUTION_DATA);
+        List<String> linesAfterSubstitution = convertToStringList(saveToFile(
+                resource));
+
+        assertEquals(linesBeforeSubstitution.size(), linesAfterSubstitution.size());
+
+        Iterator<String> beforeIt = linesBeforeSubstitution.iterator();
+        Iterator<String> afterIt = linesAfterSubstitution.iterator();
+
+        var substitutionEntry = SUBSTITUTION_DATA.entrySet().iterator().next();
+
+        boolean linesMismatch = false;
+        while (beforeIt.hasNext()) {
+            String beforeStr = beforeIt.next();
+            String afterStr = afterIt.next();
+
+            if (beforeStr.equals(afterStr)) {
+                assertFalse(beforeStr.contains(substitutionEntry.getKey()));
+            } else {
+                linesMismatch = true;
+                assertTrue(beforeStr.contains(substitutionEntry.getKey()));
+                assertTrue(afterStr.contains(substitutionEntry.getValue()));
+                assertFalse(afterStr.contains(substitutionEntry.getKey()));
+            }
+        }
+
+        assertTrue(linesMismatch);
+    }
+
+    @Test
+    public void testCustom() throws IOException {
+        testCustom(DEFAULT_NAME);
+    }
+
+    @Test
+    public void testCustomNoDefault() throws IOException {
+        testCustom(null);
+    }
+
+    private void testCustom(String defaultName) throws IOException {
+        List<String> expectedResourceData = List.of("A", "B", "C");
+
+        Path customFile = createCustomFile("foo", expectedResourceData);
+
+        List<String> actualResourceData = convertToStringList(saveToFile(
+                new OverridableResource(defaultName)
+                        .setPublicName(customFile.getFileName())
+                        .setResourceDir(customFile.getParent())));
+
+        assertArrayEquals(expectedResourceData.toArray(String[]::new),
+                actualResourceData.toArray(String[]::new));
+    }
+
+    @Test
+    public void testCustomtWithSubstitution() throws IOException {
+        testCustomtWithSubstitution(DEFAULT_NAME);
+    }
+
+    @Test
+    public void testCustomtWithSubstitutionNoDefault() throws IOException {
+        testCustomtWithSubstitution(null);
+    }
+
+    private void testCustomtWithSubstitution(String defaultName) throws IOException {
+        final List<String> resourceData = List.of("A", "[BB]", "C", "Foo",
+                "GoodbyeHello");
+        final Path customFile = createCustomFile("foo", resourceData);
+
+        final Map<String, String> substitutionData = new HashMap(Map.of("B",
+                "Bar", "Foo", "B"));
+        substitutionData.put("Hello", null);
+
+        final List<String> expectedResourceData = List.of("A", "[BarBar]", "C",
+                "B", "Goodbye");
+
+        final List<String> actualResourceData = convertToStringList(saveToFile(
+                new OverridableResource(defaultName)
+                        .setPublicName(customFile.getFileName())
+                        .setSubstitutionData(substitutionData)
+                        .setResourceDir(customFile.getParent())));
+        assertArrayEquals(expectedResourceData.toArray(String[]::new),
+                actualResourceData.toArray(String[]::new));
+
+        // Don't call setPublicName()
+        final Path dstFile = tempFolder.newFolder().toPath().resolve(customFile.getFileName());
+        new OverridableResource(defaultName)
+                .setSubstitutionData(substitutionData)
+                .setResourceDir(customFile.getParent())
+                .saveToFile(dstFile);
+        assertArrayEquals(expectedResourceData.toArray(String[]::new),
+                convertToStringList(Files.readAllBytes(dstFile)).toArray(
+                        String[]::new));
+
+        // Verify setSubstitutionData() stores a copy of passed in data
+        Map<String, String> substitutionData2 = new HashMap(substitutionData);
+        var resource = new OverridableResource(defaultName)
+                .setResourceDir(customFile.getParent());
+
+        resource.setSubstitutionData(substitutionData2);
+        substitutionData2.clear();
+        Files.delete(dstFile);
+        resource.saveToFile(dstFile);
+        assertArrayEquals(expectedResourceData.toArray(String[]::new),
+                convertToStringList(Files.readAllBytes(dstFile)).toArray(
+                        String[]::new));
+    }
+
+    @Test
+    public void testNoDefault() throws IOException {
+        Path dstFolder = tempFolder.newFolder().toPath();
+        Path dstFile = dstFolder.resolve(Path.of("foo", "bar"));
+
+        new OverridableResource(null).saveToFile(dstFile);
+
+        assertFalse(dstFile.toFile().exists());
+    }
+
+    private final static String DEFAULT_NAME;
+    private final static Map<String, String> SUBSTITUTION_DATA;
+    static {
+        if (Platform.isWindows()) {
+            DEFAULT_NAME = "WinLauncher.template";
+            SUBSTITUTION_DATA = Map.of("COMPANY_NAME", "Foo9090345");
+        } else if (Platform.isLinux()) {
+            DEFAULT_NAME = "template.control";
+            SUBSTITUTION_DATA = Map.of("APPLICATION_PACKAGE", "Package1967");
+        } else if (Platform.isMac()) {
+            DEFAULT_NAME = "Info-lite.plist.template";
+            SUBSTITUTION_DATA = Map.of("DEPLOY_BUNDLE_IDENTIFIER", "12345");
+        } else {
+            throw Platform.throwUnknownPlatformError();
+        }
+    }
+
+    private byte[] saveToFile(OverridableResource resource) throws IOException {
+        Path dstFile = tempFolder.newFile().toPath();
+        resource.saveToFile(dstFile);
+        assertThat(0, is(not(dstFile.toFile().length())));
+
+        return Files.readAllBytes(dstFile);
+    }
+
+    private Path createCustomFile(String publicName, List<String> data) throws
+            IOException {
+        Path resourceFolder = tempFolder.newFolder().toPath();
+        Path customFile = resourceFolder.resolve(publicName);
+
+        Files.write(customFile, data);
+
+        return customFile;
+    }
+
+    private static List<String> convertToStringList(byte[] data) {
+        return List.of(new String(data, StandardCharsets.UTF_8).split("\\R"));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/PathGroupTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.*;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+
+public class PathGroupTest {
+
+    @Rule
+    public final TemporaryFolder tempFolder = new TemporaryFolder();
+
+    @Test(expected = NullPointerException.class)
+    public void testNullId() {
+         new PathGroup(Map.of()).getPath(null);
+    }
+
+    @Test
+    public void testEmptyPathGroup() {
+        PathGroup pg = new PathGroup(Map.of());
+
+        assertNull(pg.getPath("foo"));
+
+        assertEquals(0, pg.paths().size());
+        assertEquals(0, pg.roots().size());
+    }
+
+    @Test
+    public void testRootsSinglePath() {
+        final PathGroup pg = new PathGroup(Map.of("main", PATH_FOO));
+
+        List<Path> paths = pg.paths();
+        assertEquals(1, paths.size());
+        assertEquals(PATH_FOO, paths.iterator().next());
+
+        List<Path> roots = pg.roots();
+        assertEquals(1, roots.size());
+        assertEquals(PATH_FOO, roots.iterator().next());
+    }
+
+    @Test
+    public void testDuplicatedRoots() {
+        final PathGroup pg = new PathGroup(Map.of("main", PATH_FOO, "another",
+                PATH_FOO, "root", PATH_EMPTY));
+
+        List<Path> paths = pg.paths();
+        Collections.sort(paths);
+
+        assertEquals(3, paths.size());
+        assertEquals(PATH_EMPTY, paths.get(0));
+        assertEquals(PATH_FOO, paths.get(1));
+        assertEquals(PATH_FOO, paths.get(2));
+
+        List<Path> roots = pg.roots();
+        assertEquals(1, roots.size());
+        assertEquals(PATH_EMPTY, roots.get(0));
+    }
+
+    @Test
+    public void testRoots() {
+        final PathGroup pg = new PathGroup(Map.of(1, Path.of("foo"), 2, Path.of(
+                "foo", "bar"), 3, Path.of("foo", "bar", "buz")));
+
+        List<Path> paths = pg.paths();
+        assertEquals(3, paths.size());
+        assertTrue(paths.contains(Path.of("foo")));
+        assertTrue(paths.contains(Path.of("foo", "bar")));
+        assertTrue(paths.contains(Path.of("foo", "bar", "buz")));
+
+        List<Path> roots = pg.roots();
+        assertEquals(1, roots.size());
+        assertEquals(Path.of("foo"), roots.get(0));
+    }
+
+    @Test
+    public void testResolveAt() {
+        final PathGroup pg = new PathGroup(Map.of(0, PATH_FOO, 1, PATH_BAR, 2,
+                PATH_EMPTY));
+
+        final Path aPath = Path.of("a");
+
+        final PathGroup pg2 = pg.resolveAt(aPath);
+        assertThat(pg, not(equalTo(pg2)));
+
+        List<Path> paths = pg.paths();
+        assertEquals(3, paths.size());
+        assertTrue(paths.contains(PATH_EMPTY));
+        assertTrue(paths.contains(PATH_FOO));
+        assertTrue(paths.contains(PATH_BAR));
+        assertEquals(PATH_EMPTY, pg.roots().get(0));
+
+        paths = pg2.paths();
+        assertEquals(3, paths.size());
+        assertTrue(paths.contains(aPath.resolve(PATH_EMPTY)));
+        assertTrue(paths.contains(aPath.resolve(PATH_FOO)));
+        assertTrue(paths.contains(aPath.resolve(PATH_BAR)));
+        assertEquals(aPath, pg2.roots().get(0));
+    }
+
+    @Test
+    public void testTransform() throws IOException {
+        for (var transform : TransformType.values()) {
+            testTransform(false, transform);
+        }
+    }
+
+    @Test
+    public void testTransformWithExcludes() throws IOException {
+        for (var transform : TransformType.values()) {
+            testTransform(true, transform);
+        }
+    }
+
+    enum TransformType { Copy, Move, Handler };
+
+    private void testTransform(boolean withExcludes, TransformType transform)
+            throws IOException {
+        final PathGroup pg = new PathGroup(Map.of(0, PATH_FOO, 1, PATH_BAR, 2,
+                PATH_EMPTY, 3, PATH_BAZ));
+
+        final Path srcDir = tempFolder.newFolder().toPath();
+        final Path dstDir = tempFolder.newFolder().toPath();
+
+        Files.createDirectories(srcDir.resolve(PATH_FOO).resolve("a/b/c/d"));
+        Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/c/file1"));
+        Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/file2"));
+        Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/file3"));
+        Files.createFile(srcDir.resolve(PATH_BAR));
+        Files.createFile(srcDir.resolve(PATH_EMPTY).resolve("file4"));
+        Files.createDirectories(srcDir.resolve(PATH_BAZ).resolve("1/2/3"));
+
+        var dst = pg.resolveAt(dstDir);
+        var src = pg.resolveAt(srcDir);
+        if (withExcludes) {
+            // Exclude from transformation.
+            src.setPath(new Object(), srcDir.resolve(PATH_FOO).resolve("a/b/c"));
+            src.setPath(new Object(), srcDir.resolve(PATH_EMPTY).resolve("file4"));
+        }
+
+        var srcFilesBeforeTransform = walkFiles(srcDir);
+
+        if (transform == TransformType.Handler) {
+            List<Map.Entry<Path, Path>> copyFile = new ArrayList<>();
+            List<Path> createDirectory = new ArrayList<>();
+            src.transform(dst, new PathGroup.TransformHandler() {
+                @Override
+                public void copyFile(Path src, Path dst) throws IOException {
+                    copyFile.add(Map.entry(src, dst));
+                }
+
+                @Override
+                public void createDirectory(Path dir) throws IOException {
+                    createDirectory.add(dir);
+                }
+            });
+
+            Consumer<Path> assertFile = path -> {
+                var entry = Map.entry(srcDir.resolve(path), dstDir.resolve(path));
+                assertTrue(copyFile.contains(entry));
+            };
+
+            Consumer<Path> assertDir = path -> {
+                assertTrue(createDirectory.contains(dstDir.resolve(path)));
+            };
+
+            assertEquals(withExcludes ? 3 : 5, copyFile.size());
+            assertEquals(withExcludes ? 8 : 10, createDirectory.size());
+
+            assertFile.accept(PATH_FOO.resolve("a/b/file2"));
+            assertFile.accept(PATH_FOO.resolve("a/b/file3"));
+            assertFile.accept(PATH_BAR);
+            assertDir.accept(PATH_FOO.resolve("a/b"));
+            assertDir.accept(PATH_FOO.resolve("a"));
+            assertDir.accept(PATH_FOO);
+            assertDir.accept(PATH_BAZ);
+            assertDir.accept(PATH_BAZ.resolve("1"));
+            assertDir.accept(PATH_BAZ.resolve("1/2"));
+            assertDir.accept(PATH_BAZ.resolve("1/2/3"));
+            assertDir.accept(PATH_EMPTY);
+
+            if (!withExcludes) {
+                assertFile.accept(PATH_FOO.resolve("a/b/c/file1"));
+                assertFile.accept(PATH_EMPTY.resolve("file4"));
+                assertDir.accept(PATH_FOO.resolve("a/b/c/d"));
+                assertDir.accept(PATH_FOO.resolve("a/b/c"));
+            }
+
+            assertArrayEquals(new Path[] { Path.of("") }, walkFiles(dstDir));
+            return;
+        }
+
+        if (transform == TransformType.Copy) {
+            src.copy(dst);
+        } else if (transform == TransformType.Move) {
+            src.move(dst);
+        }
+
+        final List<Path> excludedPaths;
+        if (withExcludes) {
+            excludedPaths = List.of(
+                PATH_EMPTY.resolve("file4"),
+                PATH_FOO.resolve("a/b/c")
+            );
+        } else {
+            excludedPaths = Collections.emptyList();
+        }
+        UnaryOperator<Path[]> removeExcludes = paths -> {
+            return Stream.of(paths)
+                    .filter(path -> !excludedPaths.stream().anyMatch(
+                            path::startsWith))
+                    .collect(Collectors.toList()).toArray(Path[]::new);
+        };
+
+        var dstFiles = walkFiles(dstDir);
+        assertArrayEquals(removeExcludes.apply(srcFilesBeforeTransform), dstFiles);
+
+        if (transform == TransformType.Copy) {
+            assertArrayEquals(dstFiles, removeExcludes.apply(walkFiles(srcDir)));
+        } else if (transform == TransformType.Move) {
+            assertFalse(Files.exists(srcDir));
+        }
+    }
+
+    private static Path[] walkFiles(Path root) throws IOException {
+        try (var files = Files.walk(root)) {
+            return files.map(root::relativize).sorted().collect(
+                    Collectors.toList()).toArray(Path[]::new);
+        }
+    }
+
+    private final static Path PATH_FOO = Path.of("foo");
+    private final static Path PATH_BAR = Path.of("bar");
+    private final static Path PATH_BAZ = Path.of("baz");
+    private final static Path PATH_EMPTY = Path.of("");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/ToolValidatorTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019, 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.incubator.jpackage.internal;
+
+import java.nio.file.Path;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+
+public class ToolValidatorTest {
+
+    @Test
+    public void testAvailable() {
+        assertNull(new ToolValidator(TOOL_JAVA).validate());
+    }
+
+    @Test
+    public void testNotAvailable() {
+        assertValidationFailure(new ToolValidator(TOOL_UNKNOWN).validate(), true);
+    }
+
+    @Test
+    public void testVersionParserUsage() {
+        // Without minimal version configured, version parser should not be used
+        new ToolValidator(TOOL_JAVA).setVersionParser(unused -> {
+            throw new RuntimeException();
+        }).validate();
+
+        // Minimal version is 1, actual is 10. Should be OK.
+        assertNull(new ToolValidator(TOOL_JAVA).setMinimalVersion(
+                new DottedVersion("1")).setVersionParser(unused -> "10").validate());
+
+        // Minimal version is 5, actual is 4.99.37. Error expected.
+        assertValidationFailure(new ToolValidator(TOOL_JAVA).setMinimalVersion(
+                new DottedVersion("5")).setVersionParser(unused -> "4.99.37").validate(),
+                false);
+
+        // Minimal version is 8, actual is 10, lexicographical comparison is used. Error expected.
+        assertValidationFailure(new ToolValidator(TOOL_JAVA).setMinimalVersion(
+                "8").setVersionParser(unused -> "10").validate(), false);
+
+        // Minimal version is 8, actual is 10, Use DottedVersion class for comparison. Should be OK.
+        assertNull(new ToolValidator(TOOL_JAVA).setMinimalVersion(
+                new DottedVersion("8")).setVersionParser(unused -> "10").validate());
+    }
+
+    private static void assertValidationFailure(ConfigException v,
+            boolean withCause) {
+        assertNotNull(v);
+        assertThat("", is(not(v.getMessage().strip())));
+        assertThat("", is(not(v.advice.strip())));
+        if (withCause) {
+            assertNotNull(v.getCause());
+        } else {
+            assertNull(v.getCause());
+        }
+    }
+
+    private final static String TOOL_JAVA;
+    private final static String TOOL_UNKNOWN = Path.of(System.getProperty(
+            "java.home"), "bin").toString();
+
+    static {
+        String fname = "java";
+        if (Platform.isWindows()) {
+            fname = fname + ".exe";
+        }
+        TOOL_JAVA = Path.of(System.getProperty("java.home"), "bin", fname).toString();
+    }
+}
--- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/AppImageFileTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2019, 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.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.LinkedHashMap;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.Rule;
-import org.junit.rules.TemporaryFolder;
-
-public class AppImageFileTest {
-
-    @Rule
-    public final TemporaryFolder tempFolder = new TemporaryFolder();
-
-    @Test
-    public void testIdentity() throws IOException {
-        Map<String, ? super Object> params = new LinkedHashMap<>();
-        params.put("name", "Foo");
-        params.put("app-version", "2.3");
-        params.put("description", "Duck is the King");
-        AppImageFile aif = create(params);
-
-        Assert.assertEquals("Foo", aif.getLauncherName());
-    }
-
-    @Test
-    public void testInvalidCommandLine() throws IOException {
-        // Just make sure AppImageFile will tolerate jpackage params that would
-        // never create app image at both load/save phases.
-        // People would edit this file just because they can.
-        // We should be ready to handle curious minds.
-        Map<String, ? super Object> params = new LinkedHashMap<>();
-        params.put("invalidParamName", "randomStringValue");
-        create(params);
-
-        params = new LinkedHashMap<>();
-        params.put("name", "foo");
-        params.put("app-version", "");
-        create(params);
-    }
-
-    @Test
-    public void testInavlidXml() throws IOException {
-        assertInvalid(createFromXml("<foo/>"));
-        assertInvalid(createFromXml("<jpackage-state/>"));
-        assertInvalid(createFromXml(
-                "<jpackage-state>",
-                    "<main-launcher></main-launcher>",
-                "</jpackage-state>"));
-        assertInvalid(createFromXml(
-                "<jpackage-state>",
-                    "<launcher>A</launcher>",
-                    "<launcher>B</launcher>",
-                "</jpackage-state>"));
-    }
-
-    @Test
-    public void testValidXml() throws IOException {
-        Assert.assertEquals("Foo", (createFromXml(
-                "<jpackage-state>",
-                    "<main-launcher>Foo</main-launcher>",
-                "</jpackage-state>")).getLauncherName());
-
-        Assert.assertEquals("Boo", (createFromXml(
-                "<jpackage-state>",
-                    "<main-launcher>Boo</main-launcher>",
-                    "<main-launcher>Bar</main-launcher>",
-                "</jpackage-state>")).getLauncherName());
-
-        var file = createFromXml(
-                "<jpackage-state>",
-                    "<main-launcher>Foo</main-launcher>",
-                    "<launcher></launcher>",
-                "</jpackage-state>");
-        Assert.assertEquals("Foo", file.getLauncherName());
-        Assert.assertArrayEquals(new String[0],
-                file.getAddLauncherNames().toArray(String[]::new));
-    }
-
-    @Test
-    public void testMainLauncherName() throws IOException {
-        Map<String, ? super Object> params = new LinkedHashMap<>();
-        params.put("name", "Foo");
-        params.put("description", "Duck App Description");
-        AppImageFile aif = create(params);
-
-        Assert.assertEquals("Foo", aif.getLauncherName());
-    }
-
-    @Test
-    public void testAddLauncherNames() throws IOException {
-        Map<String, ? super Object> params = new LinkedHashMap<>();
-        List<Map<String, ? super Object>> launchersAsMap = new ArrayList<>();
-
-        Map<String, ? super Object> addLauncher2Params = new LinkedHashMap();
-        addLauncher2Params.put("name", "Launcher2Name");
-        launchersAsMap.add(addLauncher2Params);
-
-        Map<String, ? super Object> addLauncher3Params = new LinkedHashMap();
-        addLauncher3Params.put("name", "Launcher3Name");
-        launchersAsMap.add(addLauncher3Params);
-
-        params.put("name", "Duke App");
-        params.put("description", "Duke App Description");
-        params.put("add-launcher", launchersAsMap);
-        AppImageFile aif = create(params);
-
-        List<String> addLauncherNames = aif.getAddLauncherNames();
-        Assert.assertEquals(2, addLauncherNames.size());
-        Assert.assertTrue(addLauncherNames.contains("Launcher2Name"));
-        Assert.assertTrue(addLauncherNames.contains("Launcher3Name"));
-
-    }
-
-    private AppImageFile create(Map<String, Object> params) throws IOException {
-        AppImageFile.save(tempFolder.getRoot().toPath(), params);
-        return AppImageFile.load(tempFolder.getRoot().toPath());
-    }
-
-    private void assertInvalid(AppImageFile file) {
-        Assert.assertNull(file.getLauncherName());
-        Assert.assertNull(file.getAddLauncherNames());
-    }
-
-    private AppImageFile createFromXml(String... xmlData) throws IOException {
-        Path directory = tempFolder.getRoot().toPath();
-        Path path = AppImageFile.getPathInAppImage(directory);
-        path.toFile().mkdirs();
-        Files.delete(path);
-
-        ArrayList<String> data = new ArrayList();
-        data.add("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>");
-        data.addAll(List.of(xmlData));
-
-        Files.write(path, data, StandardOpenOption.CREATE,
-                    StandardOpenOption.TRUNCATE_EXISTING);
-
-        AppImageFile image = AppImageFile.load(directory);
-        return image;
-    }
-
-}
--- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/ApplicationLayoutTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2019, 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.Files;
-import java.nio.file.Path;
-import org.junit.Test;
-import org.junit.Rule;
-import org.junit.rules.TemporaryFolder;
-import static org.junit.Assert.*;
-
-
-public class ApplicationLayoutTest {
-
-    @Rule
-    public final TemporaryFolder tempFolder = new TemporaryFolder();
-
-    private void fillLinuxAppImage() throws IOException {
-        appImage = tempFolder.newFolder("Foo").toPath();
-
-        Path base = appImage.getFileName();
-
-        tempFolder.newFolder(base.toString(), "bin");
-        tempFolder.newFolder(base.toString(), "lib", "app", "mods");
-        tempFolder.newFolder(base.toString(), "lib", "runtime", "bin");
-        tempFolder.newFile(base.resolve("bin/Foo").toString());
-        tempFolder.newFile(base.resolve("lib/app/Foo.cfg").toString());
-        tempFolder.newFile(base.resolve("lib/app/hello.jar").toString());
-        tempFolder.newFile(base.resolve("lib/Foo.png").toString());
-        tempFolder.newFile(base.resolve("lib/libapplauncher.so").toString());
-        tempFolder.newFile(base.resolve("lib/runtime/bin/java").toString());
-    }
-
-    @Test
-    public void testLinux() throws IOException {
-        fillLinuxAppImage();
-        testApplicationLayout(ApplicationLayout.linuxAppImage());
-    }
-
-    private void testApplicationLayout(ApplicationLayout layout) throws IOException {
-        ApplicationLayout srcLayout = layout.resolveAt(appImage);
-        assertApplicationLayout(srcLayout);
-
-        ApplicationLayout dstLayout = layout.resolveAt(
-                appImage.getParent().resolve(
-                        "Copy" + appImage.getFileName().toString()));
-        srcLayout.move(dstLayout);
-        Files.deleteIfExists(appImage);
-        assertApplicationLayout(dstLayout);
-
-        dstLayout.copy(srcLayout);
-        assertApplicationLayout(srcLayout);
-        assertApplicationLayout(dstLayout);
-    }
-
-    private void assertApplicationLayout(ApplicationLayout layout) throws IOException {
-        assertTrue(Files.isRegularFile(layout.appDirectory().resolve("Foo.cfg")));
-        assertTrue(Files.isRegularFile(layout.appDirectory().resolve("hello.jar")));
-        assertTrue(Files.isDirectory(layout.appModsDirectory()));
-        assertTrue(Files.isRegularFile(layout.launchersDirectory().resolve("Foo")));
-        assertTrue(Files.isRegularFile(layout.destktopIntegrationDirectory().resolve("Foo.png")));
-        assertTrue(Files.isRegularFile(layout.dllDirectory().resolve("libapplauncher.so")));
-        assertTrue(Files.isRegularFile(layout.runtimeDirectory().resolve("bin/java")));
-    }
-
-    private Path appImage;
-}
--- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/CompareDottedVersionTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-package jdk.jpackage.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Function;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-import static org.junit.Assert.*;
-
-@RunWith(Parameterized.class)
-public class CompareDottedVersionTest {
-
-    public CompareDottedVersionTest(boolean greedy, String version1,
-            String version2, int result) {
-        this.version1 = version1;
-        this.version2 = version2;
-        this.expectedResult = result;
-
-        if (greedy) {
-            createTestee = DottedVersion::greedy;
-        } else {
-            createTestee = DottedVersion::lazy;
-        }
-    }
-
-    @Parameters
-    public static List<Object[]> data() {
-        List<Object[]> data = new ArrayList<>();
-        for (var greedy : List.of(true, false)) {
-            data.addAll(List.of(new Object[][] {
-                { greedy, "00.0.0", "0", 0 },
-                { greedy, "0.035", "0.0035", 0 },
-                { greedy, "1", "1", 0 },
-                { greedy, "2", "2.0", 0 },
-                { greedy, "2.00", "2.0", 0 },
-                { greedy, "1.2.3.4", "1.2.3.4.5", -1 },
-                { greedy, "34", "33", 1 },
-                { greedy, "34.0.78", "34.1.78", -1 }
-            }));
-        }
-
-        data.addAll(List.of(new Object[][] {
-            { false, "", "1", -1 },
-            { false, "1.2.4-R4", "1.2.4-R5", 0 },
-            { false, "1.2.4.-R4", "1.2.4.R5", 0 },
-            { false, "7+1", "7+4", 0 },
-            { false, "2+14", "2-14", 0 },
-            { false, "23.4.RC4", "23.3.RC10", 1 },
-            { false, "77.0", "77.99999999999999999999999999999999999999999999999", 0 },
-        }));
-
-        return data;
-    }
-
-    @Test
-    public void testIt() {
-        int actualResult = compare(version1, version2);
-        assertEquals(expectedResult, actualResult);
-
-        int actualNegateResult = compare(version2, version1);
-        assertEquals(actualResult, -1 * actualNegateResult);
-    }
-
-    private int compare(String x, String y) {
-        int result = createTestee.apply(x).compareTo(y);
-
-        if (result < 0) {
-            return -1;
-        }
-
-        if (result > 0) {
-            return 1;
-        }
-
-        return 0;
-    }
-
-    private final String version1;
-    private final String version2;
-    private final int expectedResult;
-    private final Function<String, DottedVersion> createTestee;
-}
--- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/DeployParamsTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, 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.
- */
-package jdk.jpackage.internal;
-
-import java.io.File;
-import java.io.IOException;
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.junit.Rule;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-
-/**
- * Test for JDK-8211285
- */
-public class DeployParamsTest {
-
-    @Rule
-    public final TemporaryFolder tempFolder = new TemporaryFolder();
-
-    @Rule
-    public final ExpectedException thrown = ExpectedException.none();
-
-    @Before
-    public void setUp() throws IOException {
-        testRoot = tempFolder.newFolder();
-    }
-
-    @Test
-    public void testValidAppName() throws PackagerException {
-        initParamsAppName();
-
-        setAppNameAndValidate("Test");
-
-        setAppNameAndValidate("Test Name");
-
-        setAppNameAndValidate("Test - Name !!!");
-    }
-
-    @Test
-    public void testInvalidAppName() throws PackagerException {
-        initForInvalidAppNamePackagerException();
-        initParamsAppName();
-        setAppNameAndValidate("Test\nName");
-    }
-
-    @Test
-    public void testInvalidAppName2() throws PackagerException {
-        initForInvalidAppNamePackagerException();
-        initParamsAppName();
-        setAppNameAndValidate("Test\rName");
-    }
-
-    @Test
-    public void testInvalidAppName3() throws PackagerException {
-        initForInvalidAppNamePackagerException();
-        initParamsAppName();
-        setAppNameAndValidate("TestName\\");
-    }
-
-    @Test
-    public void testInvalidAppName4() throws PackagerException {
-        initForInvalidAppNamePackagerException();
-        initParamsAppName();
-        setAppNameAndValidate("Test \" Name");
-    }
-
-    private void initForInvalidAppNamePackagerException() {
-        thrown.expect(PackagerException.class);
-
-        String msg = "Error: Invalid Application name";
-
-        // Unfortunately org.hamcrest.core.StringStartsWith is not available
-        // with older junit, DIY
-
-        // thrown.expectMessage(startsWith("Error: Invalid Application name"));
-        thrown.expectMessage(new BaseMatcher() {
-            @Override
-            @SuppressWarnings("unchecked")
-            public boolean matches(Object o) {
-                if (o instanceof String) {
-                    return ((String) o).startsWith(msg);
-                }
-                return false;
-            }
-
-            @Override
-            public void describeTo(Description d) {
-                d.appendText(msg);
-            }
-        });
-    }
-
-    // Returns deploy params initialized to pass all validation, except for
-    // app name
-    private void initParamsAppName() {
-        params = new DeployParams();
-
-        params.setOutput(testRoot);
-        params.addResource(testRoot, new File(testRoot, "test.jar"));
-        params.addBundleArgument(Arguments.CLIOptions.APPCLASS.getId(),
-                "TestClass");
-        params.addBundleArgument(Arguments.CLIOptions.MAIN_JAR.getId(),
-                "test.jar");
-        params.addBundleArgument(Arguments.CLIOptions.INPUT.getId(), "input");
-    }
-
-    private void setAppNameAndValidate(String appName) throws PackagerException {
-        params.addBundleArgument(Arguments.CLIOptions.NAME.getId(), appName);
-        params.validate();
-    }
-
-    private File testRoot = null;
-    private DeployParams params;
-}
--- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/DottedVersionTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-package jdk.jpackage.internal;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Function;
-import java.util.stream.Stream;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import static org.junit.Assert.*;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-@RunWith(Parameterized.class)
-public class DottedVersionTest {
-
-    public DottedVersionTest(boolean greedy) {
-        this.greedy = greedy;
-        if (greedy) {
-            createTestee = DottedVersion::greedy;
-        } else {
-            createTestee = DottedVersion::lazy;
-        }
-    }
-
-    @Parameterized.Parameters
-    public static List<Object[]> data() {
-        return List.of(new Object[] { true }, new Object[] { false });
-    }
-
-    @Rule
-    public ExpectedException exceptionRule = ExpectedException.none();
-
-    @Test
-    public void testValid() {
-        final List<String> validStrings = List.of(
-            "1.0",
-            "1",
-            "2.234.045",
-            "2.234.0",
-            "0",
-            "0.1"
-        );
-
-        final List<String> validLazyStrings;
-        if (greedy) {
-            validLazyStrings = Collections.emptyList();
-        } else {
-            validLazyStrings = List.of(
-                "1.-1",
-                "5.",
-                "4.2.",
-                "3..2",
-                "2.a",
-                "0a",
-                ".",
-                " ",
-                " 1",
-                "1. 2",
-                "+1",
-                "-1",
-                "-0",
-                "1234567890123456789012345678901234567890"
-            );
-        }
-
-        Stream.concat(validStrings.stream(), validLazyStrings.stream())
-        .forEach(value -> {
-            DottedVersion version = createTestee.apply(value);
-            assertEquals(version.toString(), value);
-        });
-    }
-
-    @Test
-    public void testNull() {
-        exceptionRule.expect(NullPointerException.class);
-        createTestee.apply(null);
-    }
-
-    @Test
-    public void testEmpty() {
-        if (greedy) {
-            exceptionRule.expect(IllegalArgumentException.class);
-            exceptionRule.expectMessage("Version may not be empty string");
-            createTestee.apply("");
-        } else {
-            assertTrue(0 == createTestee.apply("").compareTo(""));
-            assertTrue(0 == createTestee.apply("").compareTo("0"));
-        }
-    }
-
-    private final boolean greedy;
-    private final Function<String, DottedVersion> createTestee;
-}
--- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/InvalidDottedVersionTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2019, 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.
- */
-package jdk.jpackage.internal;
-
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class InvalidDottedVersionTest {
-
-    public InvalidDottedVersionTest(String version) {
-        this.version = version;
-    }
-
-    @Parameters
-    public static List<Object[]> data() {
-        return Stream.of(
-            "1.-1",
-            "5.",
-            "4.2.",
-            "3..2",
-            "2.a",
-            "0a",
-            ".",
-            " ",
-            " 1",
-            "1. 2",
-            "+1",
-            "-1",
-            "-0",
-            "1234567890123456789012345678901234567890"
-        ).map(version -> new Object[] { version }).collect(Collectors.toList());
-    }
-
-    @Rule
-    public ExpectedException exceptionRule = ExpectedException.none();
-
-    @Test
-    public void testIt() {
-        exceptionRule.expect(IllegalArgumentException.class);
-        new DottedVersion(version);
-    }
-
-    private final String version;
-}
--- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/OverridableResourceTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2019, 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.*;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import jdk.jpackage.internal.resources.ResourceLocator;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.junit.Assert.*;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-public class OverridableResourceTest {
-
-    @Rule
-    public final TemporaryFolder tempFolder = new TemporaryFolder();
-
-    @Test
-    public void testDefault() throws IOException {
-        byte[] actualBytes = saveToFile(new OverridableResource(DEFAULT_NAME));
-
-        try (InputStream is = ResourceLocator.class.getResourceAsStream(
-                DEFAULT_NAME)) {
-            assertArrayEquals(is.readAllBytes(), actualBytes);
-        }
-    }
-
-    @Test
-    public void testDefaultWithSubstitution() throws IOException {
-        OverridableResource resource = new OverridableResource(DEFAULT_NAME);
-
-        List<String> linesBeforeSubstitution = convertToStringList(saveToFile(
-                resource));
-
-        if (SUBSTITUTION_DATA.size() != 1) {
-            // Test setup issue
-            throw new IllegalArgumentException(
-                    "Substitution map should contain only a single entry");
-        }
-
-        resource.setSubstitutionData(SUBSTITUTION_DATA);
-        List<String> linesAfterSubstitution = convertToStringList(saveToFile(
-                resource));
-
-        assertEquals(linesBeforeSubstitution.size(), linesAfterSubstitution.size());
-
-        Iterator<String> beforeIt = linesBeforeSubstitution.iterator();
-        Iterator<String> afterIt = linesAfterSubstitution.iterator();
-
-        var substitutionEntry = SUBSTITUTION_DATA.entrySet().iterator().next();
-
-        boolean linesMismatch = false;
-        while (beforeIt.hasNext()) {
-            String beforeStr = beforeIt.next();
-            String afterStr = afterIt.next();
-
-            if (beforeStr.equals(afterStr)) {
-                assertFalse(beforeStr.contains(substitutionEntry.getKey()));
-            } else {
-                linesMismatch = true;
-                assertTrue(beforeStr.contains(substitutionEntry.getKey()));
-                assertTrue(afterStr.contains(substitutionEntry.getValue()));
-                assertFalse(afterStr.contains(substitutionEntry.getKey()));
-            }
-        }
-
-        assertTrue(linesMismatch);
-    }
-
-    @Test
-    public void testCustom() throws IOException {
-        testCustom(DEFAULT_NAME);
-    }
-
-    @Test
-    public void testCustomNoDefault() throws IOException {
-        testCustom(null);
-    }
-
-    private void testCustom(String defaultName) throws IOException {
-        List<String> expectedResourceData = List.of("A", "B", "C");
-
-        Path customFile = createCustomFile("foo", expectedResourceData);
-
-        List<String> actualResourceData = convertToStringList(saveToFile(
-                new OverridableResource(defaultName)
-                        .setPublicName(customFile.getFileName())
-                        .setResourceDir(customFile.getParent())));
-
-        assertArrayEquals(expectedResourceData.toArray(String[]::new),
-                actualResourceData.toArray(String[]::new));
-    }
-
-    @Test
-    public void testCustomtWithSubstitution() throws IOException {
-        testCustomtWithSubstitution(DEFAULT_NAME);
-    }
-
-    @Test
-    public void testCustomtWithSubstitutionNoDefault() throws IOException {
-        testCustomtWithSubstitution(null);
-    }
-
-    private void testCustomtWithSubstitution(String defaultName) throws IOException {
-        final List<String> resourceData = List.of("A", "[BB]", "C", "Foo",
-                "GoodbyeHello");
-        final Path customFile = createCustomFile("foo", resourceData);
-
-        final Map<String, String> substitutionData = new HashMap(Map.of("B",
-                "Bar", "Foo", "B"));
-        substitutionData.put("Hello", null);
-
-        final List<String> expectedResourceData = List.of("A", "[BarBar]", "C",
-                "B", "Goodbye");
-
-        final List<String> actualResourceData = convertToStringList(saveToFile(
-                new OverridableResource(defaultName)
-                        .setPublicName(customFile.getFileName())
-                        .setSubstitutionData(substitutionData)
-                        .setResourceDir(customFile.getParent())));
-        assertArrayEquals(expectedResourceData.toArray(String[]::new),
-                actualResourceData.toArray(String[]::new));
-
-        // Don't call setPublicName()
-        final Path dstFile = tempFolder.newFolder().toPath().resolve(customFile.getFileName());
-        new OverridableResource(defaultName)
-                .setSubstitutionData(substitutionData)
-                .setResourceDir(customFile.getParent())
-                .saveToFile(dstFile);
-        assertArrayEquals(expectedResourceData.toArray(String[]::new),
-                convertToStringList(Files.readAllBytes(dstFile)).toArray(
-                        String[]::new));
-
-        // Verify setSubstitutionData() stores a copy of passed in data
-        Map<String, String> substitutionData2 = new HashMap(substitutionData);
-        var resource = new OverridableResource(defaultName)
-                .setResourceDir(customFile.getParent());
-
-        resource.setSubstitutionData(substitutionData2);
-        substitutionData2.clear();
-        Files.delete(dstFile);
-        resource.saveToFile(dstFile);
-        assertArrayEquals(expectedResourceData.toArray(String[]::new),
-                convertToStringList(Files.readAllBytes(dstFile)).toArray(
-                        String[]::new));
-    }
-
-    @Test
-    public void testNoDefault() throws IOException {
-        Path dstFolder = tempFolder.newFolder().toPath();
-        Path dstFile = dstFolder.resolve(Path.of("foo", "bar"));
-
-        new OverridableResource(null).saveToFile(dstFile);
-
-        assertFalse(dstFile.toFile().exists());
-    }
-
-    private final static String DEFAULT_NAME;
-    private final static Map<String, String> SUBSTITUTION_DATA;
-    static {
-        if (Platform.isWindows()) {
-            DEFAULT_NAME = "WinLauncher.template";
-            SUBSTITUTION_DATA = Map.of("COMPANY_NAME", "Foo9090345");
-        } else if (Platform.isLinux()) {
-            DEFAULT_NAME = "template.control";
-            SUBSTITUTION_DATA = Map.of("APPLICATION_PACKAGE", "Package1967");
-        } else if (Platform.isMac()) {
-            DEFAULT_NAME = "Info-lite.plist.template";
-            SUBSTITUTION_DATA = Map.of("DEPLOY_BUNDLE_IDENTIFIER", "12345");
-        } else {
-            throw Platform.throwUnknownPlatformError();
-        }
-    }
-
-    private byte[] saveToFile(OverridableResource resource) throws IOException {
-        Path dstFile = tempFolder.newFile().toPath();
-        resource.saveToFile(dstFile);
-        assertThat(0, is(not(dstFile.toFile().length())));
-
-        return Files.readAllBytes(dstFile);
-    }
-
-    private Path createCustomFile(String publicName, List<String> data) throws
-            IOException {
-        Path resourceFolder = tempFolder.newFolder().toPath();
-        Path customFile = resourceFolder.resolve(publicName);
-
-        Files.write(customFile, data);
-
-        return customFile;
-    }
-
-    private static List<String> convertToStringList(byte[] data) {
-        return List.of(new String(data, StandardCharsets.UTF_8).split("\\R"));
-    }
-}
--- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/PathGroupTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2019, 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.Files;
-import java.nio.file.Path;
-import java.util.*;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.not;
-import static org.junit.Assert.*;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-
-public class PathGroupTest {
-
-    @Rule
-    public final TemporaryFolder tempFolder = new TemporaryFolder();
-
-    @Test(expected = NullPointerException.class)
-    public void testNullId() {
-         new PathGroup(Map.of()).getPath(null);
-    }
-
-    @Test
-    public void testEmptyPathGroup() {
-        PathGroup pg = new PathGroup(Map.of());
-
-        assertNull(pg.getPath("foo"));
-
-        assertEquals(0, pg.paths().size());
-        assertEquals(0, pg.roots().size());
-    }
-
-    @Test
-    public void testRootsSinglePath() {
-        final PathGroup pg = new PathGroup(Map.of("main", PATH_FOO));
-
-        List<Path> paths = pg.paths();
-        assertEquals(1, paths.size());
-        assertEquals(PATH_FOO, paths.iterator().next());
-
-        List<Path> roots = pg.roots();
-        assertEquals(1, roots.size());
-        assertEquals(PATH_FOO, roots.iterator().next());
-    }
-
-    @Test
-    public void testDuplicatedRoots() {
-        final PathGroup pg = new PathGroup(Map.of("main", PATH_FOO, "another",
-                PATH_FOO, "root", PATH_EMPTY));
-
-        List<Path> paths = pg.paths();
-        Collections.sort(paths);
-
-        assertEquals(3, paths.size());
-        assertEquals(PATH_EMPTY, paths.get(0));
-        assertEquals(PATH_FOO, paths.get(1));
-        assertEquals(PATH_FOO, paths.get(2));
-
-        List<Path> roots = pg.roots();
-        assertEquals(1, roots.size());
-        assertEquals(PATH_EMPTY, roots.get(0));
-    }
-
-    @Test
-    public void testRoots() {
-        final PathGroup pg = new PathGroup(Map.of(1, Path.of("foo"), 2, Path.of(
-                "foo", "bar"), 3, Path.of("foo", "bar", "buz")));
-
-        List<Path> paths = pg.paths();
-        assertEquals(3, paths.size());
-        assertTrue(paths.contains(Path.of("foo")));
-        assertTrue(paths.contains(Path.of("foo", "bar")));
-        assertTrue(paths.contains(Path.of("foo", "bar", "buz")));
-
-        List<Path> roots = pg.roots();
-        assertEquals(1, roots.size());
-        assertEquals(Path.of("foo"), roots.get(0));
-    }
-
-    @Test
-    public void testResolveAt() {
-        final PathGroup pg = new PathGroup(Map.of(0, PATH_FOO, 1, PATH_BAR, 2,
-                PATH_EMPTY));
-
-        final Path aPath = Path.of("a");
-
-        final PathGroup pg2 = pg.resolveAt(aPath);
-        assertThat(pg, not(equalTo(pg2)));
-
-        List<Path> paths = pg.paths();
-        assertEquals(3, paths.size());
-        assertTrue(paths.contains(PATH_EMPTY));
-        assertTrue(paths.contains(PATH_FOO));
-        assertTrue(paths.contains(PATH_BAR));
-        assertEquals(PATH_EMPTY, pg.roots().get(0));
-
-        paths = pg2.paths();
-        assertEquals(3, paths.size());
-        assertTrue(paths.contains(aPath.resolve(PATH_EMPTY)));
-        assertTrue(paths.contains(aPath.resolve(PATH_FOO)));
-        assertTrue(paths.contains(aPath.resolve(PATH_BAR)));
-        assertEquals(aPath, pg2.roots().get(0));
-    }
-
-    @Test
-    public void testTransform() throws IOException {
-        for (var transform : TransformType.values()) {
-            testTransform(false, transform);
-        }
-    }
-
-    @Test
-    public void testTransformWithExcludes() throws IOException {
-        for (var transform : TransformType.values()) {
-            testTransform(true, transform);
-        }
-    }
-
-    enum TransformType { Copy, Move, Handler };
-
-    private void testTransform(boolean withExcludes, TransformType transform)
-            throws IOException {
-        final PathGroup pg = new PathGroup(Map.of(0, PATH_FOO, 1, PATH_BAR, 2,
-                PATH_EMPTY, 3, PATH_BAZ));
-
-        final Path srcDir = tempFolder.newFolder().toPath();
-        final Path dstDir = tempFolder.newFolder().toPath();
-
-        Files.createDirectories(srcDir.resolve(PATH_FOO).resolve("a/b/c/d"));
-        Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/c/file1"));
-        Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/file2"));
-        Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/file3"));
-        Files.createFile(srcDir.resolve(PATH_BAR));
-        Files.createFile(srcDir.resolve(PATH_EMPTY).resolve("file4"));
-        Files.createDirectories(srcDir.resolve(PATH_BAZ).resolve("1/2/3"));
-
-        var dst = pg.resolveAt(dstDir);
-        var src = pg.resolveAt(srcDir);
-        if (withExcludes) {
-            // Exclude from transformation.
-            src.setPath(new Object(), srcDir.resolve(PATH_FOO).resolve("a/b/c"));
-            src.setPath(new Object(), srcDir.resolve(PATH_EMPTY).resolve("file4"));
-        }
-
-        var srcFilesBeforeTransform = walkFiles(srcDir);
-
-        if (transform == TransformType.Handler) {
-            List<Map.Entry<Path, Path>> copyFile = new ArrayList<>();
-            List<Path> createDirectory = new ArrayList<>();
-            src.transform(dst, new PathGroup.TransformHandler() {
-                @Override
-                public void copyFile(Path src, Path dst) throws IOException {
-                    copyFile.add(Map.entry(src, dst));
-                }
-
-                @Override
-                public void createDirectory(Path dir) throws IOException {
-                    createDirectory.add(dir);
-                }
-            });
-
-            Consumer<Path> assertFile = path -> {
-                var entry = Map.entry(srcDir.resolve(path), dstDir.resolve(path));
-                assertTrue(copyFile.contains(entry));
-            };
-
-            Consumer<Path> assertDir = path -> {
-                assertTrue(createDirectory.contains(dstDir.resolve(path)));
-            };
-
-            assertEquals(withExcludes ? 3 : 5, copyFile.size());
-            assertEquals(withExcludes ? 8 : 10, createDirectory.size());
-
-            assertFile.accept(PATH_FOO.resolve("a/b/file2"));
-            assertFile.accept(PATH_FOO.resolve("a/b/file3"));
-            assertFile.accept(PATH_BAR);
-            assertDir.accept(PATH_FOO.resolve("a/b"));
-            assertDir.accept(PATH_FOO.resolve("a"));
-            assertDir.accept(PATH_FOO);
-            assertDir.accept(PATH_BAZ);
-            assertDir.accept(PATH_BAZ.resolve("1"));
-            assertDir.accept(PATH_BAZ.resolve("1/2"));
-            assertDir.accept(PATH_BAZ.resolve("1/2/3"));
-            assertDir.accept(PATH_EMPTY);
-
-            if (!withExcludes) {
-                assertFile.accept(PATH_FOO.resolve("a/b/c/file1"));
-                assertFile.accept(PATH_EMPTY.resolve("file4"));
-                assertDir.accept(PATH_FOO.resolve("a/b/c/d"));
-                assertDir.accept(PATH_FOO.resolve("a/b/c"));
-            }
-
-            assertArrayEquals(new Path[] { Path.of("") }, walkFiles(dstDir));
-            return;
-        }
-
-        if (transform == TransformType.Copy) {
-            src.copy(dst);
-        } else if (transform == TransformType.Move) {
-            src.move(dst);
-        }
-
-        final List<Path> excludedPaths;
-        if (withExcludes) {
-            excludedPaths = List.of(
-                PATH_EMPTY.resolve("file4"),
-                PATH_FOO.resolve("a/b/c")
-            );
-        } else {
-            excludedPaths = Collections.emptyList();
-        }
-        UnaryOperator<Path[]> removeExcludes = paths -> {
-            return Stream.of(paths)
-                    .filter(path -> !excludedPaths.stream().anyMatch(
-                            path::startsWith))
-                    .collect(Collectors.toList()).toArray(Path[]::new);
-        };
-
-        var dstFiles = walkFiles(dstDir);
-        assertArrayEquals(removeExcludes.apply(srcFilesBeforeTransform), dstFiles);
-
-        if (transform == TransformType.Copy) {
-            assertArrayEquals(dstFiles, removeExcludes.apply(walkFiles(srcDir)));
-        } else if (transform == TransformType.Move) {
-            assertFalse(Files.exists(srcDir));
-        }
-    }
-
-    private static Path[] walkFiles(Path root) throws IOException {
-        try (var files = Files.walk(root)) {
-            return files.map(root::relativize).sorted().collect(
-                    Collectors.toList()).toArray(Path[]::new);
-        }
-    }
-
-    private final static Path PATH_FOO = Path.of("foo");
-    private final static Path PATH_BAR = Path.of("bar");
-    private final static Path PATH_BAZ = Path.of("baz");
-    private final static Path PATH_EMPTY = Path.of("");
-}
--- a/test/jdk/tools/jpackage/junit/jdk/jpackage/internal/ToolValidatorTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2019, 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.nio.file.Path;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.junit.Assert.*;
-import org.junit.Test;
-
-
-public class ToolValidatorTest {
-
-    @Test
-    public void testAvailable() {
-        assertNull(new ToolValidator(TOOL_JAVA).validate());
-    }
-
-    @Test
-    public void testNotAvailable() {
-        assertValidationFailure(new ToolValidator(TOOL_UNKNOWN).validate(), true);
-    }
-
-    @Test
-    public void testVersionParserUsage() {
-        // Without minimal version configured, version parser should not be used
-        new ToolValidator(TOOL_JAVA).setVersionParser(unused -> {
-            throw new RuntimeException();
-        }).validate();
-
-        // Minimal version is 1, actual is 10. Should be OK.
-        assertNull(new ToolValidator(TOOL_JAVA).setMinimalVersion(
-                new DottedVersion("1")).setVersionParser(unused -> "10").validate());
-
-        // Minimal version is 5, actual is 4.99.37. Error expected.
-        assertValidationFailure(new ToolValidator(TOOL_JAVA).setMinimalVersion(
-                new DottedVersion("5")).setVersionParser(unused -> "4.99.37").validate(),
-                false);
-
-        // Minimal version is 8, actual is 10, lexicographical comparison is used. Error expected.
-        assertValidationFailure(new ToolValidator(TOOL_JAVA).setMinimalVersion(
-                "8").setVersionParser(unused -> "10").validate(), false);
-
-        // Minimal version is 8, actual is 10, Use DottedVersion class for comparison. Should be OK.
-        assertNull(new ToolValidator(TOOL_JAVA).setMinimalVersion(
-                new DottedVersion("8")).setVersionParser(unused -> "10").validate());
-    }
-
-    private static void assertValidationFailure(ConfigException v,
-            boolean withCause) {
-        assertNotNull(v);
-        assertThat("", is(not(v.getMessage().strip())));
-        assertThat("", is(not(v.advice.strip())));
-        if (withCause) {
-            assertNotNull(v.getCause());
-        } else {
-            assertNull(v.getCause());
-        }
-    }
-
-    private final static String TOOL_JAVA;
-    private final static String TOOL_UNKNOWN = Path.of(System.getProperty(
-            "java.home"), "bin").toString();
-
-    static {
-        String fname = "java";
-        if (Platform.isWindows()) {
-            fname = fname + ".exe";
-        }
-        TOOL_JAVA = Path.of(System.getProperty("java.home"), "bin", fname).toString();
-    }
-}
--- a/test/jdk/tools/jpackage/junit/run_junit.sh	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/junit/run_junit.sh	Fri Nov 08 14:53:03 2019 -0500
@@ -17,9 +17,10 @@
 done
 
 common_args=(\
-  --patch-module jdk.jpackage="${TESTSRC}${PS}${TESTCLASSES}" \
-  --add-reads jdk.jpackage=ALL-UNNAMED \
-  --add-exports jdk.jpackage/jdk.jpackage.internal=ALL-UNNAMED \
+  --add-modules jdk.incubator.jpackage \
+  --patch-module jdk.incubator.jpackage="${TESTSRC}${PS}${TESTCLASSES}" \
+  --add-reads jdk.incubator.jpackage=ALL-UNNAMED \
+  --add-exports jdk.incubator.jpackage/jdk.incubator.jpackage.internal=ALL-UNNAMED \
   -classpath "${TESTCLASSPATH}" \
 )
 
--- a/test/jdk/tools/jpackage/linux/AppCategoryTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/linux/AppCategoryTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -47,7 +47,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=360 -Xmx512m AppCategoryTest
  */
 public class AppCategoryTest {
--- a/test/jdk/tools/jpackage/linux/LicenseTypeTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/linux/LicenseTypeTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -42,7 +42,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=360 -Xmx512m LicenseTypeTest
  */
 public class LicenseTypeTest {
--- a/test/jdk/tools/jpackage/linux/LinuxBundleNameTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/linux/LinuxBundleNameTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -47,7 +47,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=360 -Xmx512m LinuxBundleNameTest
  */
 public class LinuxBundleNameTest {
--- a/test/jdk/tools/jpackage/linux/LinuxResourceTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/linux/LinuxResourceTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -36,7 +36,7 @@
  * @library ../helpers
  * @build jdk.jpackage.test.*
  * @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile LinuxResourceTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=LinuxResourceTest
--- a/test/jdk/tools/jpackage/linux/MaintainerTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/linux/MaintainerTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -43,7 +43,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=360 -Xmx512m MaintainerTest
  */
 public class MaintainerTest {
--- a/test/jdk/tools/jpackage/linux/PackageDepsTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/linux/PackageDepsTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -49,7 +49,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=360 -Xmx512m PackageDepsTest
  */
 public class PackageDepsTest {
--- a/test/jdk/tools/jpackage/linux/ReleaseTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/linux/ReleaseTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -46,7 +46,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=360 -Xmx512m ReleaseTest
  */
 public class ReleaseTest {
--- a/test/jdk/tools/jpackage/linux/ShortcutHintTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/linux/ShortcutHintTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -58,7 +58,7 @@
  * @requires jpackage.test.SQETest == null
  * @build jdk.jpackage.test.*
  * @requires (os.family == "linux")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile ShortcutHintTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=ShortcutHintTest
@@ -72,7 +72,7 @@
  * @build jdk.jpackage.test.*
  * @requires (os.family == "linux")
  * @requires jpackage.test.SQETest != null
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile ShortcutHintTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=ShortcutHintTest.testBasic
--- a/test/jdk/tools/jpackage/macosx/MacPropertiesTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/macosx/MacPropertiesTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -38,7 +38,7 @@
  * @library ../helpers
  * @build jdk.jpackage.test.*
  * @requires (os.family == "mac")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile MacPropertiesTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=MacPropertiesTest
--- a/test/jdk/tools/jpackage/macosx/NameWithSpaceTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/macosx/NameWithSpaceTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -40,7 +40,7 @@
  * @summary jpackage test with name containing spaces
  * @library ../helpers
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile NameWithSpaceTest.java
  * @requires (os.family == "mac")
  * @key jpackagePlatformPackage
--- a/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -43,7 +43,7 @@
  * @build SigningCheck
  * @build jtreg.SkippedException
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @requires (os.family == "mac")
  * @run main/othervm -Xmx512m SigningAppImageTest
  */
--- a/test/jdk/tools/jpackage/macosx/SigningPackageTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/macosx/SigningPackageTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -44,7 +44,7 @@
  * @build SigningCheck
  * @build jtreg.SkippedException
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @requires (os.family == "mac")
  * @run main/othervm -Xmx512m SigningPackageTest
  */
--- a/test/jdk/tools/jpackage/macosx/base/SigningCheck.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/macosx/base/SigningCheck.java	Fri Nov 08 14:53:03 2019 -0500
@@ -29,7 +29,7 @@
 import jdk.jpackage.test.TKit;
 import jdk.jpackage.test.Executor;
 
-import jdk.jpackage.internal.MacCertificate;
+import jdk.incubator.jpackage.internal.MacCertificate;
 
 public class SigningCheck {
 
--- a/test/jdk/tools/jpackage/share/AddLauncherModuleTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/AddLauncherModuleTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -28,7 +28,7 @@
  * @build JPackageHelper
  * @build JPackagePath
  * @build AddLauncherBase
- * @modules jdk.jpackage
+ * @modules jdk.incubator.jpackage
  * @run main/othervm -Xmx512m AddLauncherModuleTest
  */
 public class AddLauncherModuleTest {
--- a/test/jdk/tools/jpackage/share/AddLauncherTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/AddLauncherTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -30,7 +30,7 @@
  * @build JPackageHelper
  * @build JPackagePath
  * @build AddLauncherBase
- * @modules jdk.jpackage
+ * @modules jdk.incubator.jpackage
  * @run main/othervm -Xmx512m AddLauncherTest
  */
 public class AddLauncherTest {
--- a/test/jdk/tools/jpackage/share/AddLaunchersTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/AddLaunchersTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -28,7 +28,7 @@
  * @build JPackageHelper
  * @build JPackagePath
  * @build AddLauncherBase
- * @modules jdk.jpackage
+ * @modules jdk.incubator.jpackage
  * @run main/othervm -Xmx512m AddLaunchersTest
  */
 public class AddLaunchersTest {
--- a/test/jdk/tools/jpackage/share/AdditionalLaunchersTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/AdditionalLaunchersTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -48,7 +48,7 @@
  * @key jpackagePlatformPackage
  * @library ../helpers
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile AdditionalLaunchersTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=AdditionalLaunchersTest
@@ -155,4 +155,4 @@
         private Path icon;
         private final String name;
     }
-}
\ No newline at end of file
+}
--- a/test/jdk/tools/jpackage/share/AppImagePackageTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/AppImagePackageTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -40,7 +40,7 @@
  * @library ../helpers
  * @requires (jpackage.test.SQETest == null)
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=540 -Xmx512m AppImagePackageTest
  */
 public class AppImagePackageTest {
--- a/test/jdk/tools/jpackage/share/ArgumentsTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/ArgumentsTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -48,7 +48,7 @@
  * @summary jpackage create image with --arguments test
  * @library ../helpers
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile ArgumentsTest.java
  * @run main/othervm -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=ArgumentsTest
--- a/test/jdk/tools/jpackage/share/ErrorTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/ErrorTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -28,7 +28,7 @@
  * @build JPackageHelper
  * @build JPackagePath
  * @build Base
- * @modules jdk.jpackage
+ * @modules jdk.incubator.jpackage
  * @run main/othervm -Xmx512m ErrorTest
  */
 import java.util.*;
--- a/test/jdk/tools/jpackage/share/FileAssociationsTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/FileAssociationsTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -57,7 +57,7 @@
  * @library ../helpers
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile FileAssociationsTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=FileAssociationsTest
--- a/test/jdk/tools/jpackage/share/IconTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/IconTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -25,7 +25,7 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
-import jdk.jpackage.internal.IOUtils;
+import jdk.incubator.jpackage.internal.IOUtils;
 import jdk.jpackage.test.TKit;
 import jdk.jpackage.test.Functional;
 import jdk.jpackage.test.Annotations.*;
@@ -36,7 +36,7 @@
  * @summary jpackage create image with custom icon
  * @library ../helpers
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile IconTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=IconTest
--- a/test/jdk/tools/jpackage/share/InstallDirTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/InstallDirTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -60,7 +60,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @compile InstallDirTest.java
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=InstallDirTest.testCommon
  */
@@ -72,7 +72,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @compile InstallDirTest.java
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @requires (os.family == "linux")
  * @requires (jpackage.test.SQETest == null)
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
--- a/test/jdk/tools/jpackage/share/InvalidArgTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/InvalidArgTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -27,7 +27,7 @@
  * @library ../helpers
  * @build JPackageHelper
  * @build JPackagePath
- * @modules jdk.jpackage
+ * @modules jdk.incubator.jpackage
  * @run main/othervm -Xmx512m InvalidArgTest
  */
 public class InvalidArgTest {
--- a/test/jdk/tools/jpackage/share/JavaOptionsEqualsTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/JavaOptionsEqualsTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -31,7 +31,7 @@
  * @build JPackageHelper
  * @build JPackagePath
  * @build JavaOptionsBase
- * @modules jdk.jpackage
+ * @modules jdk.incubator.jpackage
  * @run main/othervm -Xmx512m JavaOptionsEqualsTest
  */
 public class JavaOptionsEqualsTest {
--- a/test/jdk/tools/jpackage/share/JavaOptionsModuleTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/JavaOptionsModuleTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -28,7 +28,7 @@
  * @build JPackageHelper
  * @build JPackagePath
  * @build JavaOptionsBase
- * @modules jdk.jpackage
+ * @modules jdk.incubator.jpackage
  * @run main/othervm -Xmx512m JavaOptionsModuleTest
  */
 public class JavaOptionsModuleTest {
--- a/test/jdk/tools/jpackage/share/JavaOptionsTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/JavaOptionsTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -28,7 +28,7 @@
  * @build JPackageHelper
  * @build JPackagePath
  * @build JavaOptionsBase
- * @modules jdk.jpackage
+ * @modules jdk.incubator.jpackage
  * @run main/othervm -Xmx512m JavaOptionsTest
  */
 public class JavaOptionsTest {
--- a/test/jdk/tools/jpackage/share/LicenseTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/LicenseTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -68,7 +68,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @compile LicenseTest.java
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=LicenseTest.testCommon
  */
@@ -81,7 +81,7 @@
  * @compile LicenseTest.java
  * @requires (os.family == "linux")
  * @requires (jpackage.test.SQETest == null)
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=LicenseTest.testCustomDebianCopyright
  *  --jpt-run=LicenseTest.testCustomDebianCopyrightSubst
--- a/test/jdk/tools/jpackage/share/MissingArgumentsTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/MissingArgumentsTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -27,7 +27,7 @@
  * @library ../helpers
  * @build JPackageHelper
  * @build JPackagePath
- * @modules jdk.jpackage
+ * @modules jdk.incubator.jpackage
  * @run main/othervm -Xmx512m MissingArgumentsTest
  */
 
--- a/test/jdk/tools/jpackage/share/RuntimePackageTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/RuntimePackageTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -52,7 +52,7 @@
  * @build jdk.jpackage.test.*
  * @comment Temporary disable for Linux and OSX until functionality implemented
  * @requires (os.family != "mac")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile RuntimePackageTest.java
  * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=RuntimePackageTest
--- a/test/jdk/tools/jpackage/share/SimplePackageTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/SimplePackageTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -44,7 +44,7 @@
  * @library ../helpers
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile SimplePackageTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=SimplePackageTest
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/AppVersionTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/AppVersionTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -35,7 +35,7 @@
  * @summary jpackage application version testing
  * @library ../../../../helpers
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile AppVersionTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=jdk.jpackage.tests.AppVersionTest
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/BasicTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -42,7 +42,7 @@
  * @summary jpackage basic testing
  * @library ../../../../helpers
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile BasicTest.java
  * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=jdk.jpackage.tests.BasicTest
@@ -51,8 +51,8 @@
 public final class BasicTest {
     @Test
     public void testNoArgs() {
-        List<String> output = JPackageCommand.filterOutput(
-                getJPackageToolProvider().executeAndGetOutput());
+        List<String> output =
+                getJPackageToolProvider().executeAndGetOutput();
         TKit.assertStringListEquals(List.of("Usage: jpackage <mode> <options>",
                 "Use jpackage --help (or -h) for a list of possible options"),
                 output, "Check jpackage output");
@@ -60,10 +60,10 @@
 
     @Test
     public void testVersion() {
-        List<String> output = JPackageCommand.filterOutput(
+        List<String> output =
                 getJPackageToolProvider()
                         .addArgument("--version")
-                        .executeAndGetOutput());
+                        .executeAndGetOutput();
         TKit.assertStringListEquals(List.of(System.getProperty("java.version")),
                 output, "Check jpackage output");
     }
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/MainClassTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -48,7 +48,7 @@
  * @summary test different settings of main class name for jpackage
  * @library ../../../../helpers
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile MainClassTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=jdk.jpackage.tests.MainClassTest
--- a/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/share/jdk/jpackage/tests/ModulePathTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -42,7 +42,7 @@
  * @summary jpackage with --module-path testing
  * @library ../../../../helpers
  * @build jdk.jpackage.test.*
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile ModulePathTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=jdk.jpackage.tests.ModulePathTest
--- a/test/jdk/tools/jpackage/windows/WinConsoleTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/windows/WinConsoleTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -36,7 +36,7 @@
  * @library ../helpers
  * @build jdk.jpackage.test.*
  * @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile WinConsoleTest.java
  *
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
--- a/test/jdk/tools/jpackage/windows/WinDirChooserTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/windows/WinDirChooserTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -40,7 +40,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=360 -Xmx512m WinDirChooserTest
  */
 
--- a/test/jdk/tools/jpackage/windows/WinMenuGroupTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/windows/WinMenuGroupTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -43,7 +43,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile WinMenuGroupTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=WinMenuGroupTest
--- a/test/jdk/tools/jpackage/windows/WinMenuTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/windows/WinMenuTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -40,7 +40,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile WinMenuTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=WinMenuTest
--- a/test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/windows/WinPerUserInstallTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -42,7 +42,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile WinPerUserInstallTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=WinPerUserInstallTest
--- a/test/jdk/tools/jpackage/windows/WinResourceTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/windows/WinResourceTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -42,7 +42,7 @@
  * @library ../helpers
  * @build jdk.jpackage.test.*
  * @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile WinResourceTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=WinResourceTest
--- a/test/jdk/tools/jpackage/windows/WinScriptTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/windows/WinScriptTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -25,7 +25,7 @@
 import java.nio.file.Path;
 import java.util.List;
 import java.util.ArrayList;
-import jdk.jpackage.internal.IOUtils;
+import jdk.incubator.jpackage.internal.IOUtils;
 import jdk.jpackage.test.TKit;
 import jdk.jpackage.test.PackageTest;
 import jdk.jpackage.test.PackageType;
@@ -40,7 +40,7 @@
  * @library ../helpers
  * @build jdk.jpackage.test.*
  * @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile WinScriptTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=WinScriptTest
--- a/test/jdk/tools/jpackage/windows/WinShortcutTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/windows/WinShortcutTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -41,7 +41,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile WinShortcutTest.java
  * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=WinShortcutTest
--- a/test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java	Wed Nov 06 07:20:07 2019 -0500
+++ b/test/jdk/tools/jpackage/windows/WinUpgradeUUIDTest.java	Fri Nov 08 14:53:03 2019 -0500
@@ -43,7 +43,7 @@
  * @key jpackagePlatformPackage
  * @build jdk.jpackage.test.*
  * @requires (os.family == "windows")
- * @modules jdk.jpackage/jdk.jpackage.internal
+ * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @run main/othervm/timeout=360 -Xmx512m WinUpgradeUUIDTest
  */