Merge JDK-8200758-branch
authorherrick
Mon, 27 Aug 2018 16:02:55 -0400
branchJDK-8200758-branch
changeset 56870 6668bbc41155
parent 56869 41e17fe9fbeb (diff)
parent 51536 f23312250f25 (current diff)
child 56882 0ec8559f599a
Merge
--- a/make/CompileJavaModules.gmk	Mon Aug 27 12:45:31 2018 -0700
+++ b/make/CompileJavaModules.gmk	Mon Aug 27 16:02:55 2018 -0400
@@ -384,6 +384,29 @@
 
 ################################################################################
 
+jdk.packager_ADD_JAVAC_FLAGS += -parameters -XDstringConcat=inline
+
+jdk.packager_SETUP := GENERATE_JDKBYTECODE_NOWARNINGS
+jdk.packager_COPY += .gif .png .txt .spec .script .prerm .preinst .postrm .postinst .list \
+    .desktop .copyright .control .plist .template .icns .scpt .entitlements .wxs .ico .bmp
+
+jdk.packager_CLEAN_FILES += $(wildcard \
+    $(TOPDIR)/src/jdk.packager/share/classes/jdk/packager/internal/resources/*.properties \
+    $(TOPDIR)/src/jdk.packager/share/classes/jdk/packager/internal/resources/builders/*.properties \
+    $(TOPDIR)/src/jdk.packager/linux/classes/jdk/packager/internal/resources/builders/linux/*.properties \
+    $(TOPDIR)/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/builders/mac/*.properties \
+    $(TOPDIR)/src/jdk.packager/windows/classes/jdk/packager/internal/resources/builders/windows/*.properties \
+    $(TOPDIR)/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/*.properties \
+    $(TOPDIR)/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/*.properties \
+    $(TOPDIR)/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/*.properties)
+
+################################################################################
+
+jdk.packager.services_SETUP := GENERATE_JDKBYTECODE_NOWARNINGS
+jdk.packager.services_COPY += .gif .png .txt
+
+################################################################################
+
 jdk.jconsole_COPY += .gif .png
 
 jdk.jconsole_CLEAN_FILES += $(wildcard \
--- a/make/common/Modules.gmk	Mon Aug 27 12:45:31 2018 -0700
+++ b/make/common/Modules.gmk	Mon Aug 27 16:02:55 2018 -0400
@@ -128,6 +128,8 @@
 JRE_TOOL_MODULES += \
     jdk.jdwp.agent \
     jdk.pack \
+    jdk.packager \
+    jdk.packager.services \
     jdk.scripting.nashorn.shell \
     #
 
@@ -168,6 +170,8 @@
     jdk.naming.rmi \
     jdk.net \
     jdk.pack \
+    jdk.packager \
+    jdk.packager.services \
     jdk.rmic \
     jdk.scripting.nashorn \
     jdk.sctp \
@@ -227,6 +231,14 @@
 endif
 
 ################################################################################
+# Some platforms don't have jpackager
+
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+  MODULES_FILTER += jdk.packager
+  MODULES_FILTER += jdk.packager.services
+endif
+
+################################################################################
 # Module list macros
 
 # Use append so that the custom extension may add to these variables
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/launcher/Launcher-jdk.packager.gmk	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,66 @@
+#
+# Copyright (c) 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.
+#
+
+include LauncherCommon.gmk
+
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+
+JPACKAGEREXE_SRC := $(TOPDIR)/src/jdk.packager/windows/native/jpackager
+
+$(eval $(call SetupJdkExecutable, BUILD_JPACKAGEREXE, \
+    NAME := jpackager, \
+    SRC := $(JPACKAGEREXE_SRC), \
+    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+    OPTIMIZATION := LOW, \
+    CFLAGS := $(CXXFLAGS_JDKEXE) -nologo -DFULL  -EHsc \
+	  -DWIN32 -D_LITTLE_ENDIAN -DWIN32_LEAN_AND_MEAN \
+	  -DUNICODE -D_UNICODE, \
+    CFLAGS_release := -DPRODUCT, \
+    DISABLED_WARNINGS_gcc := unused-result implicit-fallthrough, \
+    LDFLAGS := $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) -nologo \
+        $(call SET_SHARED_LIBRARY_ORIGIN), \
+    LIBS := $(LIBCXX) user32.lib shell32.lib advapi32.lib ole32.lib, \
+    VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
+))
+
+TARGETS += $(BUILD_JPACKAGEREXE)
+
+else
+
+#copy script for Unix
+$(eval $(call SetupCopyFiles, COPY_JPACKAGERSCRIPT, \
+    SRC := $(TOPDIR)/src/jdk.packager/unix/scripts/, \
+    DEST := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE), \
+    FILES := jpackager, \
+))
+
+TARGETS += $(COPY_JPACKAGERSCRIPT)
+
+endif
+
+################################################################################
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/lib/Lib-jdk.packager.gmk	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,122 @@
+#
+# Copyright (c) 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.
+#
+
+include LibCommon.gmk
+
+################################################################################
+
+LIBPACKAGER_SRC_ROOT := $(TOPDIR)/src/jdk.packager
+LIBPACKAGER_SHARED_SRC := $(LIBPACKAGER_SRC_ROOT)/share/native/library/common
+LIBPACKAGER_PLATFORM_SRC := $(LIBPACKAGER_SRC_ROOT)/$(OPENJDK_TARGET_OS)/native/library
+
+BUILD_LIBPACKAGER_SRC :=
+
+#FIXME: make separate directories for each platform
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+  BUILD_LIBPACKAGER_SRC := $(LIBPACKAGER_PLATFORM_SRC)
+endif
+BUILD_LIBPACKAGER_SRC += $(LIBPACKAGER_SHARED_SRC)
+
+
+# Output shared library and debug symbols files in the same directory as .obj files.
+$(eval $(call SetupJdkLibrary, BUILD_LIBPACKAGER, \
+    NAME := packager, \
+    SRC := $(BUILD_LIBPACKAGER_SRC), \
+    OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libpackager, \
+    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+    OPTIMIZATION := LOW, \
+    CFLAGS := $(CXXFLAGS_JDKLIB) -I$(LIBPACKAGER_SHARED_SRC), \
+    CFLAGS_windows :=  -nologo -EHsc -D_WINDOWS -DUNICODE -D_UNICODE -DWIN32 -D_LITTLE_ENDIAN -DWIN32_LEAN_AND_MEAN, \
+    LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
+        $(call SET_SHARED_LIBRARY_ORIGIN), \
+    LIBS_windows := user32.lib shell32.lib advapi32.lib ole32.lib, \
+    CFLAGS_linux :=  -Wextra -Wformat -Wformat-security -c -fPIC, \
+    LDFLAGS_macosx := -ldl -dynamiclib -framework Cocoa -stdlib=libc++, \
+    LDFLAGS_linux :=  -ldl -shared -lpthread -static-libstdc++, \
+    VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
+))
+
+$(BUILD_LIBPACKAGER): $(call FindLib, java.base, java)
+
+TARGETS += $(BUILD_LIBPACKAGER)
+
+################################################################################
+
+PACKAGERAPPLAUNCHEREXE_SRC := $(TOPDIR)/src/jdk.packager/$(OPENJDK_TARGET_OS)/native/launcher
+
+
+# Output executable and debug symbols files in the same directory as .obj files.
+$(eval $(call SetupJdkExecutable, BUILD_PACKAGERAPPLAUNCHEREXE, \
+    NAME := papplauncher, \
+    SRC := $(PACKAGERAPPLAUNCHEREXE_SRC), \
+    OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/papplauncher, \
+    TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
+    OPTIMIZATION := LOW, \
+    CFLAGS := $(CXXFLAGS_JDKEXE) -DFULL, \
+    CFLAGS_release := -DPRODUCT, \
+    CFLAGS_linux := -fPIC, \
+    CFLAGS_solaris := -KPIC, \
+    CFLAGS_macosx := -fPIC, \
+    CFLAGS_windows :=  -nologo -EHsc -D_WINDOWS -DUNICODE -D_UNICODE -DWIN32 -D_LITTLE_ENDIAN -DWIN32_LEAN_AND_MEAN, \
+    DISABLED_WARNINGS_gcc := unused-result implicit-fallthrough, \
+    LDFLAGS := $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \
+        $(call SET_SHARED_LIBRARY_ORIGIN), \
+    LDFLAGS_macosx := -framework Cocoa -stdlib=libstdc++, \
+    LIBS := $(LIBCXX), \
+    LIBS_solaris :=  -lc, \
+    LDFLAGS_linux :=  -ldl -static-libstdc++, \
+    LIBS_windows :=  user32.lib shell32.lib advapi32.lib, \
+    VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
+))
+
+TARGETS += $(BUILD_PACKAGERAPPLAUNCHEREXE)
+
+################################################################################
+
+
+# Copy debug symbols to module lib output directory so that JDK build system put them in jdk/bin directory.
+# Copy binaries to module classes output directory so that JDK build system put them in module resources.
+
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+  RESOURCE_SUBDIR := mac
+else
+  RESOURCE_SUBDIR := $(OPENJDK_TARGET_OS)
+endif
+
+SetupCopyTargetFiles = \
+    $(eval $(call SetupCopyFiles, COPY_DEBUG_SYMBOLS_$1, \
+        SRC := $(dir $(firstword $($1))), \
+        DEST := $(INSTALL_LIBRARIES_HERE), \
+        FILES := $(notdir $(filter %.diz %.pdb %.map, $($1))) \
+    )) \
+    $(eval $(call SetupCopyFiles, COPY_BINARIES_$1, \
+        SRC := $(dir $(firstword $($1))), \
+        DEST := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/packager/internal/resources/$(RESOURCE_SUBDIR), \
+        FILES := $(notdir $(firstword $($1))) \
+    )) \
+    $(eval TARGETS += $(COPY_DEBUG_SYMBOLS_$1) $(COPY_BINARIES_$1))
+
+$(call SetupCopyTargetFiles,BUILD_LIBPACKAGER)
+$(call SetupCopyTargetFiles,BUILD_PACKAGERAPPLAUNCHEREXE)
--- a/src/jdk.jlink/share/classes/module-info.java	Mon Aug 27 12:45:31 2018 -0700
+++ b/src/jdk.jlink/share/classes/module-info.java	Mon Aug 27 16:02:55 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -76,4 +76,7 @@
         jdk.tools.jlink.internal.plugins.IncludeLocalesPlugin,
         jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin,
         jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin;
+
+    exports jdk.tools.jlink.internal.packager to
+        jdk.packager;
  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager.services/share/classes/jdk/packager/services/UserJvmOptionsService.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, 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.packager.services;
+
+import jdk.packager.services.userjvmoptions.PreferencesUserJvmOptions;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+/**
+ * Runtime access to the UserJVMOptions.
+ *
+ * This class is not typically available in the Java Runtime, you must
+ * explicitly include the 'jdk.packager.services' module from the jmod directory
+ * of the JDK as part of your application bundle.
+ *
+ * @since 9
+ */
+public interface UserJvmOptionsService {
+
+    /**
+     * Get the instance of UserJvmOptionService to use.  Which one to use is
+     * configured by the packager and the launcher.  Do not directly
+     * instantiate any instance of this interface, use this method to get
+     * an appropriate instance.
+     *
+     * @return the instance of UserJvmOptionsService for your application.
+     */
+    static UserJvmOptionsService getUserJVMDefaults() {
+        ServiceLoader<UserJvmOptionsService> loader =
+            ServiceLoader.load(UserJvmOptionsService.class);
+        Iterator<UserJvmOptionsService> iter = loader.iterator();
+        if (iter.hasNext()) {
+            return iter.next();
+        } else {
+            return new PreferencesUserJvmOptions();
+        }
+    }
+
+    /**
+     * The "current" set of UserJVMOptions.
+     *
+     * This will take effect on the next application start, and this may not
+     * reflect the current set of UserJVMOptions used to start this application.
+     *
+     * @return A map of the keys and values.  Alterations to this map will not
+     *         change the stored UserJVMOptions
+     */
+    Map<String, String> getUserJVMOptions();
+
+    /**
+     * Sets the passed in options as the UserJVMOptions.
+     *
+     * If the application has specified default values and those keys are not
+     * in this map, they will be replaced by the default values.
+     *
+     * No validation or error checking is performed on these values.  It is
+     * entirely possible that you may provide a set of UserJVMOptions that
+     * may prevent the normal startup of your application and may require
+     * manual intervention to resolve.
+     *
+     * @param options The UserJVMOptions to set.
+     */
+    void setUserJVMOptions(Map<String, String> options);
+
+    /**
+     * The "default" set of UserJVMOptions.
+     *
+     * This returns the default set of keys and values that the application has
+     * been configured to use.
+     *
+     * @return the keys and values of the default UserJVMOptions.
+     * @throws UnsupportedOperationException if the defaults cannot be calculated.
+     */
+    Map<String, String> getUserJVMOptionDefaults();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager.services/share/classes/jdk/packager/services/package.html	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<!--
+/*
+ * Copyright (c) 2017, 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.
+ */
+-->
+
+<html>
+<head>
+  <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
+  <title>jdk.packager.services</title>
+</head>
+<body>
+<p>Defines the services used by the jpackager tool. This package is
+not typically available in the Java Runtime, you must explicitly include
+the 'jdk.packager.services' module from the jmod directory of
+the JDK as part of your application bundle.</p>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager.services/share/classes/jdk/packager/services/singleton/SingleInstanceImpl.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2017, 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.packager.services.singleton;
+
+import java.awt.Desktop;
+import java.awt.desktop.OpenFilesHandler;
+import java.awt.desktop.OpenFilesEvent;
+import java.net.ServerSocket;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.io.File;
+import java.io.PrintStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+import java.security.PrivilegedAction;
+import java.security.AccessController;
+import java.security.SecureRandom;
+
+
+class SingleInstanceImpl {
+
+    static final String SI_FILEDIR = getTmpDir() + File.separator
+                                                 + "si" + File.separator;
+    static final String SI_MAGICWORD = "javapackager.singleinstance.init";
+    static final String SI_ACK = "javapackager.singleinstance.ack";
+    static final String SI_STOP = "javapackager.singleinstance.stop";
+    static final String SI_EOF = "javapackager.singleinstance.EOF";
+
+    private final ArrayList<SingleInstanceListener> siListeners =
+            new ArrayList<>();
+    private SingleInstanceServer siServer;
+
+    private static final SecureRandom random = new SecureRandom();
+    private static volatile boolean serverStarted = false;
+    private static int randomNumber;
+
+    private final Object lock = new Object();
+
+    static String getSingleInstanceFilePrefix(final String stringId) {
+        String filePrefix = stringId.replace('/','_');
+        filePrefix = filePrefix.replace(':','_');
+        return filePrefix;
+    }
+
+    static String getTmpDir() {
+        String os = System.getProperty("os.name").toLowerCase();
+        if (os.contains("win")) {
+            return System.getProperty("user.home")
+                    + "\\AppData\\LocalLow\\Sun\\Java\\Packager\\tmp";
+        } else if (os.contains("mac") || os.contains("os x")) {
+            return System.getProperty("user.home")
+                    + "/Library/Application Support/Oracle/Java/Packager/tmp";
+        } else if (os.contains("nix") || os.contains("nux")
+                || os.contains("aix")) {
+            return System.getProperty("user.home") + "/.java/packager/tmp";
+        }
+
+        return System.getProperty("java.io.tmpdir");
+    }
+
+    void addSingleInstanceListener(SingleInstanceListener sil, String id) {
+
+        if (sil == null || id == null) {
+            return;
+        }
+
+        // start a new server thread for this unique id
+        // first time
+        synchronized (lock) {
+            if (!serverStarted) {
+                SingleInstanceService.trace("unique id: " + id);
+                try {
+                    siServer = new SingleInstanceServer(id);
+                    siServer.start();
+                } catch (Exception e) {
+                    SingleInstanceService.trace(
+                            "addSingleInstanceListener failed");
+                    SingleInstanceService.trace(e);
+                    return; // didn't start
+                }
+                serverStarted = true;
+            }
+        }
+
+        synchronized (siListeners) {
+            // add the sil to the arrayList
+            if (!siListeners.contains(sil)) {
+                siListeners.add(sil);
+            }
+        }
+
+    }
+
+    class SingleInstanceServer {
+
+        private final SingleInstanceServerRunnable runnable;
+        private final Thread thread;
+
+        SingleInstanceServer(SingleInstanceServerRunnable runnable)
+                throws IOException {
+            thread = new Thread(null, runnable, "JavaPackagerSIThread",
+                                0, false);
+            thread.setDaemon(true);
+            this.runnable = runnable;
+        }
+
+        SingleInstanceServer(String stringId) throws IOException {
+            this(new SingleInstanceServerRunnable(stringId));
+        }
+
+        int getPort() {
+            return runnable.getPort();
+        }
+
+        void start() {
+            thread.start();
+        }
+    }
+
+    private class SingleInstanceServerRunnable implements Runnable {
+
+        ServerSocket ss;
+        int port;
+        String stringId;
+        String[] arguments;
+
+        int getPort() {
+            return port;
+        }
+
+        SingleInstanceServerRunnable(String id) throws IOException {
+            stringId = id;
+
+            // open a free ServerSocket
+            ss = null;
+
+            // we should bind the server to the local InetAddress 127.0.0.1
+            // port number is automatically allocated for current SI
+            ss = new ServerSocket(0, 0, InetAddress.getByName("127.0.0.1"));
+
+            // get the port number
+            port = ss.getLocalPort();
+            SingleInstanceService.trace("server port at: " + port);
+
+            // create the single instance file with canonical home and port num
+            createSingleInstanceFile(stringId, port);
+        }
+
+        private String getSingleInstanceFilename(final String id,
+                final int port) {
+            String name = SI_FILEDIR + getSingleInstanceFilePrefix(id)
+                    + "_" + port;
+            SingleInstanceService.trace("getSingleInstanceFilename: " + name);
+            return name;
+        }
+
+        private void removeSingleInstanceFile(final String id, final int port) {
+            new File(getSingleInstanceFilename(id, port)).delete();
+            SingleInstanceService.trace("removed SingleInstanceFile: "
+                                        + getSingleInstanceFilename(id, port));
+        }
+
+        private void createSingleInstanceFile(final String id, final int port) {
+            String filename = getSingleInstanceFilename(id, port);
+            final File siFile = new File(filename);
+            final File siDir = new File(SI_FILEDIR);
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                @Override
+                public Void run() {
+                    siDir.mkdirs();
+                    String[] fList = siDir.list();
+                    if (fList != null) {
+                        String prefix = getSingleInstanceFilePrefix(id);
+                        for (String file : fList) {
+                            // if file with the same prefix exist, remove it
+                            if (file.startsWith(prefix)) {
+                                SingleInstanceService.trace(
+                                        "file should be removed: "
+                                         + SI_FILEDIR + file);
+                                new File(SI_FILEDIR + file).delete();
+                            }
+                        }
+                    }
+
+                    PrintStream out = null;
+                    try {
+                        siFile.createNewFile();
+                        siFile.deleteOnExit();
+                        // write random number to single instance file
+                        out = new PrintStream(new FileOutputStream(siFile));
+                        randomNumber = random.nextInt();
+                        out.print(randomNumber);
+                    } catch (IOException ioe) {
+                        SingleInstanceService.trace(ioe);
+                    } finally {
+                        if (out != null) {
+                            out.close();
+                        }
+                    }
+                    return null;
+                }
+            });
+        }
+
+        @Override
+        public void run() {
+            // start sil to handle all the incoming request
+            // from the server port of the current url
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                @Override
+                public Void run() {
+                    List<String> recvArgs = new ArrayList<>();
+                    while (true) {
+                        recvArgs.clear();
+                        InputStream is = null;
+                        BufferedReader in = null;
+                        InputStreamReader isr = null;
+                        Socket s = null;
+                        String line = null;
+                        boolean sendAck = false;
+                        int port = -1;
+                        String charset = null;
+                        try {
+                            SingleInstanceService.trace("waiting connection");
+                            s = ss.accept();
+                            is = s.getInputStream();
+                            // read first byte for encoding type
+                            int encoding = is.read();
+                            if (encoding ==
+                                SingleInstanceService.ENCODING_PLATFORM) {
+                                charset = Charset.defaultCharset().name();
+                            } else if (encoding ==
+                                    SingleInstanceService.ENCODING_UNICODE) {
+                                charset =
+                                    SingleInstanceService.ENCODING_UNICODE_NAME;
+                            } else {
+                                SingleInstanceService.trace(
+                                    "SingleInstanceImpl - unknown encoding");
+                                return null;
+                            }
+                            isr = new InputStreamReader(is, charset);
+                            in = new BufferedReader(isr);
+                            // first read the random number
+                            line = in.readLine();
+                            if (line.equals(String.valueOf(randomNumber)) ==
+                                    false) {
+                                // random number does not match
+                                // should not happen
+                                // shutdown server socket
+                                removeSingleInstanceFile(stringId, port);
+                                ss.close();
+                                serverStarted = false;
+                                SingleInstanceService.trace("Unexpected Error, "
+                                        + "SingleInstanceService disabled");
+                                return null;
+                            } else {
+                                line = in.readLine();
+                                // no need to continue reading if MAGICWORD
+                                // did not come first
+                                SingleInstanceService.trace("recv: " + line);
+                                if (line.equals(SI_MAGICWORD)) {
+                                    SingleInstanceService.trace(
+                                            "got magic word.");
+                                    while (true) {
+                                        // Get input string
+                                        try {
+                                            line = in.readLine();
+                                            if (line != null
+                                                    && line.equals(SI_EOF)) {
+                                                // end of file reached
+                                                break;
+                                            } else {
+                                                recvArgs.add(line);
+                                            }
+                                        } catch (IOException ioe) {
+                                            SingleInstanceService.trace(ioe);
+                                        }
+                                    }
+                                    arguments = recvArgs.toArray(
+                                            new String[recvArgs.size()]);
+                                    sendAck = true;
+                                } else if (line.equals(SI_STOP)) {
+                                    // remove the SingleInstance file
+                                    removeSingleInstanceFile(stringId, port);
+                                    break;
+                                }
+                            }
+                        } catch (IOException ioe) {
+                            SingleInstanceService.trace(ioe);
+                        } finally {
+                            try {
+                                if (sendAck) {
+                                    // let the action listener handle the rest
+                                    for (String arg : arguments) {
+                                        SingleInstanceService.trace(
+                                                "Starting new instance with "
+                                                + "arguments: arg:" + arg);
+                                    }
+
+                                    performNewActivation(arguments);
+
+                                    // now the event is handled, we can send
+                                    // out the ACK
+                                    SingleInstanceService.trace(
+                                            "sending out ACK");
+                                    if (s != null) {
+                                        try (OutputStream os =
+                                                s.getOutputStream();
+                                            PrintStream ps = new PrintStream(os,
+                                                    true, charset)) {
+                                            // send OK (ACK)
+                                            ps.println(SI_ACK);
+                                            ps.flush();
+                                        }
+                                    }
+                                }
+
+                                if (in != null) {
+                                    in.close();
+                                }
+
+                                if (isr != null) {
+                                    isr.close();
+                                }
+
+                                if (is != null) {
+                                    is.close();
+                                }
+
+                                if (s != null) {
+                                    s.close();
+                                }
+                            } catch (IOException ioe) {
+                                SingleInstanceService.trace(ioe);
+                            }
+                        }
+                    }
+                    return null;
+                }
+            });
+        }
+    }
+
+    private void performNewActivation(final String[] args) {
+        // enumerate the sil list and call
+        // each sil with arguments
+        @SuppressWarnings("unchecked")
+        ArrayList<SingleInstanceListener> silal =
+                (ArrayList<SingleInstanceListener>)siListeners.clone();
+        silal.forEach(sil -> sil.newActivation(args));
+    }
+
+    void setOpenFileHandler() {
+        String os = System.getProperty("os.name").toLowerCase();
+        if (!os.contains("mac") && !os.contains("os x")) {
+            return;
+        }
+
+        Desktop.getDesktop().setOpenFileHandler(new OpenFilesHandler() {
+            @Override
+            public void openFiles(OpenFilesEvent e) {
+                List<String> arguments = new ArrayList<>();
+                e.getFiles().forEach(file -> arguments.add(file.toString()));
+                performNewActivation(arguments.toArray(
+                                    new String[arguments.size()]));
+            }
+        });
+    }
+
+    void removeSingleInstanceListener(SingleInstanceListener sil) {
+        if (sil == null) {
+            return;
+        }
+
+        synchronized (siListeners) {
+
+            if (!siListeners.remove(sil)) {
+                return;
+            }
+
+            if (siListeners.isEmpty()) {
+                 AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    @Override
+                    public Void run() {
+                        // stop server
+                        Socket socket = null;
+                        PrintStream out = null;
+                        OutputStream os = null;
+                        try {
+                            socket = new Socket("127.0.0.1",
+                                    siServer.getPort());
+                            os = socket.getOutputStream();
+                            byte[] encoding = new byte[1];
+                            encoding[0] =
+                                    SingleInstanceService.ENCODING_PLATFORM;
+                            os.write(encoding);
+                            String charset = Charset.defaultCharset().name();
+                            out = new PrintStream(os, true, charset);
+                            out.println(randomNumber);
+                            out.println(SingleInstanceImpl.SI_STOP);
+                            out.flush();
+                            serverStarted = false;
+                        } catch (IOException ioe) {
+                            SingleInstanceService.trace(ioe);
+                        } finally {
+                            try {
+                                if (out != null) {
+                                    out.close();
+                                }
+                                if (os != null) {
+                                    os.close();
+                                }
+                                if (socket != null) {
+                                    socket.close();
+                                }
+                            } catch (IOException ioe) {
+                                SingleInstanceService.trace(ioe);
+                            }
+                        }
+                        return null;
+                    }
+               });
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager.services/share/classes/jdk/packager/services/singleton/SingleInstanceListener.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017, 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.packager.services.singleton;
+
+/**
+ * The {@code SingleInstanceListener} interface is used for implementing
+ * Single Instance functionality for Java Packager.
+ *
+ * @since 10
+ */
+public interface SingleInstanceListener {
+
+    /**
+     * This method should be implemented by the application to
+     * handle the single instance behaviour - how should the application
+     * handle the arguments when another instance of the application is
+     * invoked with params.
+     *
+     * @param params parameters for the application main
+     */
+    public void newActivation(String... params);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager.services/share/classes/jdk/packager/services/singleton/SingleInstanceNewActivation.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, 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.packager.services.singleton;
+
+import java.util.Arrays;
+
+// This class is used for notifying Single Instance for Java Packager.
+
+public class SingleInstanceNewActivation {
+
+    public static void main(String[] args) {
+
+        if (args.length < 2) {
+            // no user args specified
+            return;
+        }
+
+        // the first arg is process id of the single instance
+        String appId = SingleInstanceService.APP_ID_PREFIX + args[0];
+
+        if (SingleInstanceService.isServerRunning(appId)) {
+            String[] newArgs = Arrays.copyOfRange(args, 1, args.length);
+            SingleInstanceService.connectToServer(newArgs);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager.services/share/classes/jdk/packager/services/singleton/SingleInstanceService.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2017, 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.packager.services.singleton;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.Socket;
+import java.nio.charset.Charset;
+
+/**
+ * The {@code SingleInstanceService} class provides public methods for using
+ * Single Instance functionality for Java Packager. To use these methods,
+ * the option named "-singleton" must be specified on javapackager command line.
+ *
+ * @since 10
+ */
+public class SingleInstanceService {
+
+    static private boolean DEBUG = false;
+    static private PrintStream DEBUG_STREAM = null;
+
+    static private int currPort;
+    static private String stringId = null;
+    static private String randomNumberString = null;
+
+    static private SingleInstanceImpl instance = null;
+
+    static final int ENCODING_PLATFORM = 1;
+    static final int ENCODING_UNICODE = 2;
+
+    static final String ENCODING_PLATFORM_NAME = "UTF-8";
+    static final String ENCODING_UNICODE_NAME = "UTF-16LE";
+
+    static final String APP_ID_PREFIX = "javapackager.si.";
+
+    private SingleInstanceService() {}
+
+    static void enableDebug(boolean enable, PrintStream stream) {
+        DEBUG = enable;
+        DEBUG_STREAM = stream;
+    }
+
+    static void trace(String message) {
+        if (DEBUG && DEBUG_STREAM != null) {
+            DEBUG_STREAM.println(message);
+        }
+    }
+
+    static void trace(Throwable t) {
+        if (DEBUG && DEBUG_STREAM != null) {
+            t.printStackTrace(DEBUG_STREAM);
+        }
+    }
+
+    /**
+     * Registers {@code SingleInstanceListener} for current process.
+     * If the {@code SingleInstanceListener} object is already registered, or
+     * {@code slistener} is {@code null}, then the registration is skipped.
+     *
+     * @param slistener the listener to handle the single instance behaviour.
+     */
+    public static void registerSingleInstance(
+            SingleInstanceListener slistener) {
+        registerSingleInstance(slistener, false);
+    }
+
+    /**
+     * Registers {@code SingleInstanceListener} for current process.
+     * If the {@code SingleInstanceListener} object is already registered, or
+     * {@code slistener} is {@code null}, then the registration is skipped.
+     *
+     * @param slistener the listener to handle the single instance behaviour.
+     * @param setFileHandler if {@code true}, the listener is notified when the
+     *         application is asked to open a list of files. If OS is not MacOS,
+     *         the parameter is ignored.
+     */
+    public static void registerSingleInstance(SingleInstanceListener slistener,
+                                              boolean setFileHandler) {
+        String appId = APP_ID_PREFIX + ProcessHandle.current().pid();
+        registerSingleInstanceForId(slistener, appId, setFileHandler);
+    }
+
+    static void registerSingleInstanceForId(SingleInstanceListener slistener,
+            String stringId, boolean setFileHandler) {
+        // register SingleInstanceListener for given Id
+        instance = new SingleInstanceImpl();
+        instance.addSingleInstanceListener(slistener, stringId);
+        if (setFileHandler) {
+            instance.setOpenFileHandler();
+        }
+    }
+
+    /**
+     * Unregisters {@code SingleInstanceListener} for current process.
+     * If the {@code SingleInstanceListener} object is not registered, or
+     * {@code slistener} is {@code null}, then the unregistration is skipped.
+     *
+     * @param slistener the listener for unregistering.
+     */
+    public static void unregisterSingleInstance(
+            SingleInstanceListener slistener) {
+        instance.removeSingleInstanceListener(slistener);
+    }
+
+    /**
+     * Returns true if single instance server is running for the id
+     */
+    static boolean isServerRunning(String id) {
+        trace("isServerRunning ? : "+ id);
+        File siDir = new File(SingleInstanceImpl.SI_FILEDIR);
+        String[] fList = siDir.list();
+        if (fList != null) {
+            String prefix = SingleInstanceImpl.getSingleInstanceFilePrefix(id);
+            for (String file : fList) {
+                trace("isServerRunning: " + file);
+                trace("\t String id: " + id);
+                trace("\t SingleInstanceFilePrefix: " + prefix);
+                // if file with the same prefix already exist, server is running
+                if (file.startsWith(prefix)) {
+                    try {
+                        currPort = Integer.parseInt(
+                                    file.substring(file.lastIndexOf('_') + 1));
+                        trace("isServerRunning: " + file
+                                + ": port: " + currPort);
+                    } catch (NumberFormatException nfe) {
+                        trace("isServerRunning: " + file
+                                + ": port parsing failed");
+                        trace(nfe);
+                        return false;
+                    }
+
+                    trace("Server running at port: " + currPort);
+                    File siFile = new File(SingleInstanceImpl.SI_FILEDIR, file);
+
+                    // get random number from single instance file
+                    try (BufferedReader br = new BufferedReader(
+                            new FileReader(siFile))) {
+                        randomNumberString = br.readLine();
+                        trace("isServerRunning: " + file + ": magic: "
+                                + randomNumberString);
+                    } catch (IOException ioe ) {
+                        trace("isServerRunning: " + file
+                                + ": reading magic failed");
+                        trace(ioe);
+                    }
+                    trace("isServerRunning: " + file + ": setting id - OK");
+                    stringId = id;
+                    return true;
+                } else {
+                    trace("isServerRunning: " + file + ": prefix NOK");
+                }
+            }
+        } else {
+            trace("isServerRunning: empty file list");
+        }
+        trace("isServerRunning: false");
+        return false;
+    }
+
+    /**
+     * Returns true if we connect successfully to the server for the stringId
+     */
+    static boolean connectToServer(String[] args) {
+        trace("Connect to: " + stringId + " " + currPort);
+
+        if (randomNumberString == null) {
+            // should not happen
+            trace("MAGIC number is null, bail out.");
+            return false;
+        }
+
+        // Now we open the tcpSocket and the stream
+        Socket socket = null;
+        OutputStream os = null;
+        PrintStream out = null;
+        InputStreamReader isr = null;
+        BufferedReader br = null;
+        try {
+            socket = new Socket("127.0.0.1", currPort);
+            os = socket.getOutputStream();
+            byte[] encoding = new byte[1];
+            encoding[0] = ENCODING_PLATFORM;
+            os.write(encoding);
+            String encodingName = Charset.defaultCharset().name();
+
+            out = new PrintStream(os, true, encodingName);
+            isr = new InputStreamReader(socket.getInputStream(), encodingName);
+            br = new BufferedReader(isr);
+
+            // send random number
+            out.println(randomNumberString);
+            // send MAGICWORD
+            out.println(SingleInstanceImpl.SI_MAGICWORD);
+
+            for (String arg : args) {
+                out.println(arg);
+            }
+
+            // indicate end of file transmission
+            out.println(SingleInstanceImpl.SI_EOF);
+            out.flush();
+
+            // wait for ACK (OK) response
+            trace("Waiting for ack");
+            final int tries = 5;
+
+            // try to listen for ACK
+            for (int i=0; i < tries; i++) {
+                String str = br.readLine();
+                if (str != null && str.equals(SingleInstanceImpl.SI_ACK)) {
+                    trace("Got ACK");
+                    return true;
+                }
+            }
+        } catch (java.net.SocketException se) {
+            // no server is running - continue launch
+            trace("No server is running - continue launch.");
+            trace(se);
+        } catch (Exception ioe) {
+            trace(ioe);
+        }
+        finally {
+            try {
+                if (br != null) {
+                    br.close();
+                }
+                if (isr != null) {
+                    isr.close();
+                }
+                if (out != null) {
+                    out.close();
+                }
+                if (os != null) {
+                    os.close();
+                }
+                if (socket != null) {
+                    socket.close();
+                }
+            } catch (IOException ioe) {
+                trace(ioe);
+            }
+        }
+        trace("No ACK from server, bail out.");
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager.services/share/classes/jdk/packager/services/userjvmoptions/LauncherUserJvmOptions.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2014, 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.packager.services.userjvmoptions;
+
+import jdk.packager.services.UserJvmOptionsService;
+
+import java.security.AllPermission;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * Access the UserJVMOptions via a native library provided by the launcher.
+ *
+ * Do not instantiate this class directly, instead use
+ * {@see jdk.packager.services.UserJvmOptionsService#getUserJVMDefaults()}
+ * to get an instance.
+ *
+ * @since 8u40
+ */
+final public class LauncherUserJvmOptions implements UserJvmOptionsService {
+
+    private static final Object semaphore = new Object();
+
+    static {
+        try {
+            checkAllPermissions();
+            System.loadLibrary("packager");
+        } catch (SecurityException se) {
+            se.printStackTrace(System.err);
+            // fail to load, we will also throw on all public methods
+        }
+    }
+
+    private static void checkAllPermissions() {
+        final SecurityManager securityManager = System.getSecurityManager();
+        if (securityManager != null) {
+            securityManager.checkPermission(new AllPermission());
+        }
+    }
+
+    /**
+     * Access the default User JVM Option for a specific key
+     *
+     * @param option the key for the User JVM Option
+     *
+     * @return the default value of the user JVM Option.  Currently set user
+     * values are not considered, and only the default is returned.  If there
+     * is no default value then null is returned.
+     */
+    private static native String _getUserJvmOptionDefaultValue(String option);
+
+    /**
+     * This lists the keys for User JVM Options that will have a default
+     * provided by the launcher.
+     *
+     * This list will be a subset of the keys used by the launcher and only
+     * lists those values that will have a default value provided if the user
+     * does not set a value of their own.
+     *
+     * @return an array of keys in no particular order.
+     */
+    private static native String[] _getUserJvmOptionDefaultKeys();
+    /**
+     * Access the current User JVM Option for a specific key
+     *
+     * @param option the key for the User JVM Option
+     *
+     * @return the current value of the user JVM Option.  If the user has not
+     * set a value then the default value is returned, except in the case where
+     * there is no default value, where null is returned.
+     */
+    private static native String _getUserJvmOptionValue(String option);
+
+    /**
+     * Update the all User JVM Options
+     *
+     * All option/value pairs will be replaced with the values provided. The
+     * parameters options and values are paired at the same index.
+     * Example: options[3] = -Xmx and values[3] = 999m
+     * This cannot be used to adjust default values.
+     *
+     * @param options the keys for the User JVM Options
+     * @param values the values for the User JVM Options
+     */
+    private static native void _setUserJvmKeysAndValues(String[] options,
+                                                        String[] values);
+
+    /**
+     * This lists the keys for all User JVM Options that will be used by the
+     * launcher.
+     *
+     * This list will be a superset of the defaults as may also include user
+     * values that do not have a default.
+     *
+     * @return an array of keys in no particular order.
+     */
+    private static native String[] _getUserJvmOptionKeys();
+
+    @Override
+    public Map<String, String> getUserJVMOptions() {
+        checkAllPermissions();
+        synchronized (semaphore) {
+            Map<String, String> results = new LinkedHashMap<>();
+            for (String s : _getUserJvmOptionKeys()) {
+                results.put(s, _getUserJvmOptionValue(s));
+            }
+            return results;
+        }
+    }
+
+    @Override
+    public void setUserJVMOptions(Map<String, String> options) {
+        checkAllPermissions();
+        synchronized (semaphore) {
+            List<String> keys = new LinkedList<>();
+            List<String> values = new LinkedList<>();
+
+            for (Map.Entry<String, String> option : options.entrySet()) {
+                if (option.getKey() == null) {
+                    throw new IllegalArgumentException(
+                        "For Launcher Backed UserJVMOptions keys in the "
+                            + "UserJVMOptions map cannot be null.");
+                }
+                if (option.getValue() == null) {
+                    throw new IllegalArgumentException(
+                        "For Launcher Backed UserJVMOptions values in the "
+                            + "UserJVMOptions map cannot be null. Keys are "
+                            + "removed by absence, not by setting keys to null."
+                    );
+                }
+                keys.add(option.getKey());
+                values.add(option.getValue());
+            }
+
+            _setUserJvmKeysAndValues(keys.toArray(new String[keys.size()]),
+                    values.toArray(new String[values.size()]));
+        }
+    }
+
+    @Override
+    public Map<String, String> getUserJVMOptionDefaults() {
+        checkAllPermissions();
+        synchronized (semaphore) {
+            Map<String, String> results = new LinkedHashMap<>();
+            for (String s : _getUserJvmOptionDefaultKeys()) {
+                results.put(s, _getUserJvmOptionDefaultValue(s));
+            }
+            return results;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager.services/share/classes/jdk/packager/services/userjvmoptions/PreferencesUserJvmOptions.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 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.packager.services.userjvmoptions;
+
+import jdk.packager.services.UserJvmOptionsService;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+
+/**
+ * Access to old preferences based UserJvmOptions
+ *
+ * Do not instantiate this class directly, instead use
+ * {@see jdk.packager.services.UserJvmOptionsService#getUserJVMDefaults()}
+ * to get an instance.
+ *
+ * @since 8u40
+ */
+final public class PreferencesUserJvmOptions implements UserJvmOptionsService {
+
+    Preferences node = Preferences.userRoot().node(System.getProperty(
+        "app.preferences.id").replace(".", "/")).node("JVMUserOptions");
+
+    @Override
+    public Map<String, String> getUserJVMOptions() {
+        Map<String, String> result = new LinkedHashMap<>();
+        try {
+            for (String s : node.childrenNames()) {
+                String o = node.get(s, null);
+                if (o != null) {
+                    result.put(s, o);
+                }
+            }
+        } catch (BackingStoreException ignore) {
+        }
+
+        return result;
+    }
+
+    @Override
+    public void setUserJVMOptions(Map<String, String> options) {
+        try {
+            node.clear();
+            for (Map.Entry<String, String> entry : options.entrySet()) {
+                node.put(entry.getKey(), entry.getValue());
+            }
+            node.flush();
+        } catch (BackingStoreException ignore) {
+        }
+
+    }
+
+    @Override
+    public Map<String, String> getUserJVMOptionDefaults() {
+        throw new UnsupportedOperationException(
+          "Preferences backed UserJvmOptions do not enumerate their defaults");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager.services/share/classes/module-info.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * Defines the services used by the jpackager tool.
+ *
+ * @moduleGraph
+ * @since 11
+ */
+module jdk.packager.services {
+    exports jdk.packager.services;
+    exports jdk.packager.services.singleton;
+
+    requires java.prefs;
+    requires java.desktop;
+
+    uses jdk.packager.services.UserJvmOptionsService;
+
+    provides jdk.packager.services.UserJvmOptionsService with jdk.packager.services.userjvmoptions.LauncherUserJvmOptions;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/builders/linux/LinuxAppImageBuilder.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2015, 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.packager.internal.builders.linux;
+
+
+import jdk.packager.internal.BundlerParamInfo;
+import jdk.packager.internal.IOUtils;
+import jdk.packager.internal.Log;
+import jdk.packager.internal.RelativeFileSet;
+import jdk.packager.internal.StandardBundlerParam;
+import jdk.packager.internal.resources.linux.LinuxResources;
+import jdk.packager.internal.builders.AbstractAppImageBuilder;
+
+import java.io.File;
+import java.io.FileInputStream;
+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.nio.file.Files;
+import java.nio.file.Path;
+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 static jdk.packager.internal.StandardBundlerParam.*;
+
+public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+        "jdk.packager.internal.resources.builders.linux.LinuxAppImageBuilder");
+
+    protected static final String LINUX_BUNDLER_PREFIX =
+            BUNDLER_PREFIX + "linux" + File.separator;
+    private static final String EXECUTABLE_NAME = "JavaAppLauncher";
+    private static final String LIBRARY_NAME = "libpackager.so";
+
+    private final Path root;
+    private final Path appDir;
+    private final Path runtimeDir;
+    private final Path resourcesDir;
+    private final Path mdir;
+
+    private final Map<String, ? super Object> params;
+
+    public static final BundlerParamInfo<File> ICON_PNG =
+            new StandardBundlerParam<>(
+            I18N.getString("param.icon-png.name"),
+            I18N.getString("param.icon-png.description"),
+            "icon.png",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".png")) {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "message.icon-not-png"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+    public LinuxAppImageBuilder(Map<String, Object> config, Path imageOutDir)
+            throws IOException {
+        super(config,
+                imageOutDir.resolve(APP_NAME.fetchFrom(config) + "/runtime"));
+
+        Objects.requireNonNull(imageOutDir);
+
+        this.root = imageOutDir.resolve(APP_NAME.fetchFrom(config));
+        this.appDir = root.resolve("app");
+        this.runtimeDir = root.resolve("runtime");
+        this.resourcesDir = root.resolve("resources");
+        this.mdir = runtimeDir.resolve("lib");
+        this.params = new HashMap<>();
+        config.entrySet().stream().forEach(e -> params.put(
+                e.getKey().toString(), e.getValue()));
+        Files.createDirectories(appDir);
+        Files.createDirectories(runtimeDir);
+        Files.createDirectories(resourcesDir);
+    }
+    
+    public LinuxAppImageBuilder(String appName, Path imageOutDir)
+            throws IOException {
+        super(null, imageOutDir.resolve(appName));
+
+        Objects.requireNonNull(imageOutDir);
+
+        this.root = imageOutDir.resolve(appName);
+        this.appDir = null;
+        this.runtimeDir = null;
+        this.resourcesDir = null;
+        this.mdir = null;
+        this.params = new HashMap<>();
+    }
+
+    private Path destFile(String dir, String filename) {
+        return runtimeDir.resolve(dir).resolve(filename);
+    }
+
+    private void writeEntry(InputStream in, Path dstFile) throws IOException {
+        Files.createDirectories(dstFile.getParent());
+        Files.copy(in, dstFile);
+    }
+
+    private void writeSymEntry(Path dstFile, Path target) throws IOException {
+        Files.createDirectories(dstFile.getParent());
+        Files.createLink(dstFile, target);
+    }
+
+    /**
+     * chmod ugo+x file
+     */
+    private void setExecutable(Path file) {
+        try {
+            Set<PosixFilePermission> perms =
+                    Files.getPosixFilePermissions(file);
+            perms.add(PosixFilePermission.OWNER_EXECUTE);
+            perms.add(PosixFilePermission.GROUP_EXECUTE);
+            perms.add(PosixFilePermission.OTHERS_EXECUTE);
+            Files.setPosixFilePermissions(file, perms);
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    private static void createUtf8File(File file, String content)
+            throws IOException {
+        try (OutputStream fout = new FileOutputStream(file);
+            Writer output = new OutputStreamWriter(fout, "UTF-8")) {
+            output.write(content);
+        }
+    }
+
+
+    //it is static for the sake of sharing with "installer" bundlers
+    // that may skip calls to validate/bundle in this class!
+    public static File getRootDir(File outDir, Map<String, ? super Object> p) {
+        return new File(outDir, APP_FS_NAME.fetchFrom(p));
+    }
+
+    public static String getLauncherName(Map<String, ? super Object> p) {
+        return APP_FS_NAME.fetchFrom(p);
+    }
+
+    public static String getLauncherCfgName(Map<String, ? super Object> p) {
+        return "app/" + APP_FS_NAME.fetchFrom(p) + ".cfg";
+    }
+
+    @Override
+    public InputStream getResourceAsStream(String name) {
+        return LinuxResources.class.getResourceAsStream(name);
+    }
+
+    @Override
+    public void prepareApplicationFiles() throws IOException {
+        Map<String, ? super Object> originalParams = new HashMap<>(params);
+
+        try {
+            // create the primary launcher
+            createLauncherForEntryPoint(params, root);
+
+            // Copy library to the launcher folder
+            try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
+               writeEntry(is_lib,  root.resolve(LIBRARY_NAME));
+            }
+
+            // create the secondary launchers, if any
+            List<Map<String, ? super Object>> entryPoints =
+                    StandardBundlerParam.SECONDARY_LAUNCHERS.fetchFrom(params);
+            for (Map<String, ? super Object> entryPoint : entryPoints) {
+                Map<String, ? super Object> tmp = new HashMap<>(originalParams);
+                tmp.putAll(entryPoint);
+                // remove name.fs that was calculated for main launcher.
+                // otherwise, wrong launcher name will be selected.
+                tmp.remove(APP_FS_NAME.getID());
+                createLauncherForEntryPoint(tmp, root);
+            }
+
+            // Copy class path entries to Java folder
+            copyApplication();
+
+            // Copy icon to Resources folder
+            copyIcon();
+
+        } catch (IOException ex) {
+            Log.info("Exception: " + ex);
+            Log.debug(ex);
+        }
+    }
+
+    @Override
+    public void prepareServerJreFiles() throws IOException {}
+
+    private void createLauncherForEntryPoint(Map<String, ? super Object> p,
+            Path rootDir) throws IOException {
+        // Copy executable to Linux folder
+        Path executableFile = root.resolve(getLauncherName(p));
+        try (InputStream is_launcher = getResourceAsStream("papplauncher")) {
+            writeEntry(is_launcher, executableFile);
+        }
+
+        executableFile.toFile().setExecutable(true, false);
+        executableFile.toFile().setWritable(true, true);
+
+        writeCfgFile(p, root.resolve(getLauncherCfgName(p)).toFile(),
+                "$APPDIR/runtime");
+    }
+
+    private void copyIcon() throws IOException {
+        File icon = ICON_PNG.fetchFrom(params);
+        if (icon != null) {
+            File iconTarget = new File(resourcesDir.toFile(),
+                    APP_FS_NAME.fetchFrom(params) + ".png");
+            IOUtils.copyFile(icon, iconTarget);
+        }
+    }
+
+    private void copyApplication() 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);
+            }
+        }
+    }
+
+    @Override
+    protected String getCacheLocation(Map<String, ? super Object> params) {
+        return "$CACHEDIR/";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/linux/LinuxAppBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.linux;
+
+import jdk.packager.internal.AbstractImageBundler;
+import jdk.packager.internal.BundlerParamInfo;
+import jdk.packager.internal.ConfigException;
+import jdk.packager.internal.IOUtils;
+import jdk.packager.internal.JreUtils;
+import jdk.packager.internal.JreUtils.Rule;
+import jdk.packager.internal.Log;
+import jdk.packager.internal.Platform;
+import jdk.packager.internal.RelativeFileSet;
+import jdk.packager.internal.StandardBundlerParam;
+import jdk.packager.internal.Arguments;
+import jdk.packager.internal.UnsupportedPlatformException;
+import jdk.packager.internal.bundlers.BundleParams;
+import jdk.packager.internal.builders.linux.LinuxAppImageBuilder;
+import jdk.packager.internal.resources.linux.LinuxResources;
+
+import jdk.packager.internal.JLinkBundlerHelper;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import static jdk.packager.internal.StandardBundlerParam.*;
+import jdk.packager.internal.builders.AbstractAppImageBuilder;
+
+public class LinuxAppBundler extends AbstractImageBundler {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle(
+                    "jdk.packager.internal.resources.linux.LinuxAppBundler");
+
+    protected static final String LINUX_BUNDLER_PREFIX =
+            BUNDLER_PREFIX + "linux" + File.separator;
+    private static final String EXECUTABLE_NAME = "JavaAppLauncher";
+
+    public static final BundlerParamInfo<File> ICON_PNG =
+            new StandardBundlerParam<>(
+            I18N.getString("param.icon-png.name"),
+            I18N.getString("param.icon-png.description"),
+            "icon.png",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".png")) {
+                    Log.info(MessageFormat.format(
+                            I18N.getString("message.icon-not-png"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+    public static final BundlerParamInfo<URL> RAW_EXECUTABLE_URL =
+            new StandardBundlerParam<>(
+            I18N.getString("param.raw-executable-url.name"),
+            I18N.getString("param.raw-executable-url.description"),
+            "linux.launcher.url",
+            URL.class,
+            params -> LinuxResources.class.getResource(EXECUTABLE_NAME),
+            (s, p) -> {
+                try {
+                    return new URL(s);
+                } catch (MalformedURLException e) {
+                    Log.info(e.toString());
+                    return null;
+                }
+            });
+
+    //Subsetting of JRE is restricted.
+    //JRE README defines what is allowed to strip:
+    //   http://www.oracle.com/technetwork/java/javase/jre-8-readme-2095710.html
+    //
+    public static final BundlerParamInfo<Rule[]> LINUX_JRE_RULES =
+            new StandardBundlerParam<>(
+            "",
+            "",
+            ".linux.runtime.rules",
+            Rule[].class,
+            params -> new Rule[]{
+                    Rule.prefixNeg("/bin"),
+                    Rule.prefixNeg("/plugin"),
+                    //Rule.prefixNeg("/lib/ext"), 
+                    //need some of jars there for https to work
+                    Rule.suffix("deploy.jar"), //take deploy.jar
+                    Rule.prefixNeg("/lib/deploy"),
+                    Rule.prefixNeg("/lib/desktop"),
+                    Rule.substrNeg("libnpjp2.so")
+            },
+            (s, p) ->  null
+    );
+
+    public static final BundlerParamInfo<RelativeFileSet> LINUX_RUNTIME =
+            new StandardBundlerParam<>(
+            I18N.getString("param.runtime.name"),
+            I18N.getString("param.runtime.description"),
+            BundleParams.PARAM_RUNTIME,
+            RelativeFileSet.class,
+            params -> JreUtils.extractJreAsRelativeFileSet(
+                    System.getProperty("java.home"),
+                    LINUX_JRE_RULES.fetchFrom(params)),
+            (s, p) -> JreUtils.extractJreAsRelativeFileSet(s,
+                    LINUX_JRE_RULES.fetchFrom(p))
+    );
+
+    public static final BundlerParamInfo<String> LINUX_INSTALL_DIR =
+            new StandardBundlerParam<>(
+            I18N.getString("param.linux-install-dir.name"),
+            I18N.getString("param.linux-install-dir.description"),
+            "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
+    );
+    
+    public static final BundlerParamInfo<String> LINUX_PACKAGE_DEPENDENCIES =
+            new StandardBundlerParam<>(
+            I18N.getString("param.linux-package-dependencies.name"),
+            I18N.getString("param.linux-package-dependencies.description"),
+            Arguments.CLIOptions.LINUX_PACKAGE_DEPENDENCIES.getId(),
+            String.class,
+            params -> {
+                 return "";
+             },
+            (s, p) -> s
+    );
+
+    @Override
+    public boolean validate(Map<String, ? super Object> p)
+            throws UnsupportedPlatformException, ConfigException {
+        try {
+            if (p == null) throw new ConfigException(
+                    I18N.getString("error.parameters-null"),
+                    I18N.getString("error.parameters-null.advice"));
+
+            return doValidate(p);
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    //used by chained bundlers to reuse validation logic
+    boolean doValidate(Map<String, ? super Object> p)
+            throws UnsupportedPlatformException, ConfigException {
+        if (Platform.getPlatform() != Platform.LINUX) {
+            throw new UnsupportedPlatformException();
+        }
+
+        imageBundleValidation(p);
+
+        return true;
+    }
+
+    //it is static for the sake of sharing with "installer" bundlers
+    // that may skip calls to validate/bundle in this class!
+    public static File getRootDir(File outDir, Map<String, ? super Object> p) {
+        return new File(outDir, APP_FS_NAME.fetchFrom(p));
+    }
+
+    public static String getLauncherCfgName(Map<String, ? super Object> p) {
+        return "app/" + APP_FS_NAME.fetchFrom(p) +".cfg";
+    }
+
+    File doBundle(Map<String, ? super Object> p, File outputDirectory,
+            boolean dependentTask) {
+        if (Arguments.CREATE_JRE_INSTALLER.fetchFrom(p)) {
+            return doJreBundle(p, outputDirectory, dependentTask);
+        } else {
+            return doAppBundle(p, outputDirectory, dependentTask);
+        }
+    }
+
+    private File doJreBundle(Map<String, ? super Object> p,
+            File outputDirectory, boolean dependentTask) {
+        try {
+            File rootDirectory = createRoot(p, outputDirectory, dependentTask);
+            AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder(
+                    APP_NAME.fetchFrom(p), outputDirectory.toPath());
+            File predefined = PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
+            if (predefined == null ) {
+                JLinkBundlerHelper.generateServerJre(p, appBuilder);
+            } else {
+                return predefined;
+            }
+            return rootDirectory;
+        } catch (IOException ex) {
+            Log.info("Exception: "+ex);
+            Log.debug(ex);
+            return null;
+        } catch (Exception ex) {
+            Log.info("Exception: "+ex);
+            Log.debug(ex);
+            return null;
+        }
+    }
+
+    private File doAppBundle(Map<String, ? super Object> p,
+            File outputDirectory, boolean dependentTask) {
+        try {
+            File rootDirectory = createRoot(p, outputDirectory, dependentTask);
+            AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder(p,
+                    outputDirectory.toPath());
+            if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {
+                JLinkBundlerHelper.execute(p, appBuilder);
+            } else {
+                StandardBundlerParam.copyPredefinedRuntimeImage(p, appBuilder);
+            }
+            return rootDirectory;
+        } catch (IOException ex) {
+            Log.info("Exception: "+ex);
+            Log.debug(ex);
+            return null;
+        } catch (Exception ex) {
+            Log.info("Exception: "+ex);
+            Log.debug(ex);
+            return null;
+        }
+    }
+
+    private File createRoot(Map<String, ? super Object> p,
+            File outputDirectory, boolean dependentTask) throws IOException {
+        if (!outputDirectory.isDirectory() && !outputDirectory.mkdirs()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-create-output-dir"),
+                    outputDirectory.getAbsolutePath()));
+        }
+        if (!outputDirectory.canWrite()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-write-to-output-dir"),
+                    outputDirectory.getAbsolutePath()));
+        }
+
+        // Create directory structure
+        File rootDirectory = getRootDir(outputDirectory, p);
+        IOUtils.deleteRecursive(rootDirectory);
+        rootDirectory.mkdirs();
+
+        if (!dependentTask) {
+            Log.info(MessageFormat.format(I18N.getString(
+                    "message.creating-bundle-location"),
+                    rootDirectory.getAbsolutePath()));
+        }
+
+        if (!p.containsKey(JLinkBundlerHelper.JLINK_BUILDER.getID())) {
+            p.put(JLinkBundlerHelper.JLINK_BUILDER.getID(),
+                    "linuxapp-image-builder");
+        }
+ 
+        return rootDirectory;
+    }
+
+    @Override
+    public String getName() {
+        return I18N.getString("bundler.name");
+    }
+
+    @Override
+    public String getDescription() {
+        return I18N.getString("bundler.description");
+    }
+
+    @Override
+    public String getID() {
+        return "linux.app";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "IMAGE";
+    }
+
+    @Override
+    public Collection<BundlerParamInfo<?>> getBundleParameters() {
+        return getAppBundleParameters();
+    }
+
+    public static Collection<BundlerParamInfo<?>> getAppBundleParameters() {
+        return Arrays.asList(
+                APP_NAME,
+                APP_RESOURCES,
+                ARGUMENTS,
+                CLASSPATH,
+                JVM_OPTIONS,
+                JVM_PROPERTIES,
+                LINUX_RUNTIME,
+                MAIN_CLASS,
+                MAIN_JAR,
+                PREFERENCES_ID,
+                PRELOADER_CLASS,
+                USER_JVM_OPTIONS,
+                VERSION,
+                VERBOSE
+        );
+    }
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) {
+        return doBundle(params, outputParentDir, false);
+    }
+    
+    @Override    
+    public boolean supported() {
+        // TODO: check that it really works on Solaris (in case we need it)
+        return (Platform.getPlatform() == Platform.LINUX) ||
+                (Platform.getPlatform() == Platform.SOLARIS);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/linux/LinuxDebBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,1038 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.linux;
+
+import jdk.packager.internal.*;
+import jdk.packager.internal.Arguments;
+import jdk.packager.internal.bundlers.BundleParams;
+import jdk.packager.internal.resources.linux.LinuxResources;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+import static jdk.packager.internal.StandardBundlerParam.*;
+import static jdk.packager.internal.linux.LinuxAppBundler.ICON_PNG;
+import static jdk.packager.internal.linux.LinuxAppBundler.LINUX_INSTALL_DIR;
+import static
+        jdk.packager.internal.linux.LinuxAppBundler.LINUX_PACKAGE_DEPENDENCIES;
+
+public class LinuxDebBundler extends AbstractBundler {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle(
+                    "jdk.packager.internal.resources.linux.LinuxDebBundler");
+
+    public static final BundlerParamInfo<LinuxAppBundler> APP_BUNDLER =
+            new StandardBundlerParam<>(
+            I18N.getString("param.app-bundler.name"),
+            I18N.getString("param.app-bundler.description"),
+            "linux.app.bundler",
+            LinuxAppBundler.class,
+            params -> new LinuxAppBundler(),
+            (s, p) -> null);
+
+    // 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_BUNDLE_NAME_PATTERN =
+            Pattern.compile("^[a-z][a-z\\d\\+\\-\\.]+");
+
+    public static final BundlerParamInfo<String> BUNDLE_NAME =
+            new StandardBundlerParam<> (
+            I18N.getString("param.bundle-name.name"),
+            I18N.getString("param.bundle-name.description"),
+            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_BUNDLE_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;
+            });
+
+    public static final BundlerParamInfo<String> FULL_PACKAGE_NAME =
+            new StandardBundlerParam<> (
+            I18N.getString("param.full-package-name.name"),
+            I18N.getString("param.full-package-name.description"),
+            "linux.deb.fullPackageName",
+            String.class,
+            params -> BUNDLE_NAME.fetchFrom(params) + "-"
+                    + VERSION.fetchFrom(params),
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<File> CONFIG_ROOT =
+            new StandardBundlerParam<>(
+            I18N.getString("param.config-root.name"),
+            I18N.getString("param.config-root.description"),
+            "configRoot",
+            File.class,
+            params ->  new File(BUILD_ROOT.fetchFrom(params), "linux"),
+            (s, p) -> new File(s));
+
+    public static final BundlerParamInfo<File> DEB_IMAGE_DIR =
+            new StandardBundlerParam<>(
+            I18N.getString("param.image-dir.name"),
+            I18N.getString("param.image-dir.description"),
+            "linux.deb.imageDir",
+            File.class,
+            params -> {
+                File imagesRoot = IMAGES_ROOT.fetchFrom(params);
+                if (!imagesRoot.exists()) imagesRoot.mkdirs();
+                return new File(new File(imagesRoot, "linux-deb.image"),
+                        FULL_PACKAGE_NAME.fetchFrom(params));
+            },
+            (s, p) -> new File(s));
+
+    public static final BundlerParamInfo<File> APP_IMAGE_ROOT =
+            new StandardBundlerParam<>(
+            I18N.getString("param.app-image-root.name"),
+            I18N.getString("param.app-image-root.description"),
+            "linux.deb.imageRoot",
+            File.class,
+            params -> {
+                File imageDir = DEB_IMAGE_DIR.fetchFrom(params);
+                return new File(imageDir, LINUX_INSTALL_DIR.fetchFrom(params));
+            },
+            (s, p) -> new File(s));
+
+    public static final BundlerParamInfo<File> CONFIG_DIR =
+            new StandardBundlerParam<>(
+            I18N.getString("param.config-dir.name"),
+            I18N.getString("param.config-dir.description"),
+            "linux.deb.configDir",
+            File.class,
+            params ->  new File(DEB_IMAGE_DIR.fetchFrom(params), "DEBIAN"),
+            (s, p) -> new File(s));
+
+    public static final BundlerParamInfo<String> EMAIL =
+            new StandardBundlerParam<> (
+            I18N.getString("param.maintainer-email.name"),
+            I18N.getString("param.maintainer-email.description"),
+            BundleParams.PARAM_EMAIL,
+            String.class,
+            params -> "Unknown",
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<String> MAINTAINER =
+            new StandardBundlerParam<> (
+            I18N.getString("param.maintainer-name.name"),
+            I18N.getString("param.maintainer-name.description"),
+            Arguments.CLIOptions.LINUX_DEB_MAINTAINER.getId(),
+            String.class,
+            params -> VENDOR.fetchFrom(params) + " <"
+                    + EMAIL.fetchFrom(params) + ">",
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<String> LICENSE_TEXT =
+            new StandardBundlerParam<> (
+            I18N.getString("param.license-text.name"),
+            I18N.getString("param.license-text.description"),
+            "linux.deb.licenseText",
+            String.class,
+            params -> {
+                try {
+                    List<String> licenseFiles = LICENSE_FILE.fetchFrom(params);
+
+                    //need to copy license file to the root of linux-app.image
+                    if (licenseFiles.size() > 0) {
+                        String licFileStr = licenseFiles.get(0);
+
+                        for (RelativeFileSet rfs :
+                                APP_RESOURCES_LIST.fetchFrom(params)) {
+                            if (rfs.contains(licFileStr)) {
+                                return new String(IOUtils.readFully(
+                                        new File(rfs.getBaseDirectory(),
+                                                 licFileStr)));
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    if (Log.isDebug()) {
+                        e.printStackTrace();
+                    }
+                }
+                return "Unknown";
+            },
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<String> XDG_FILE_PREFIX =
+            new StandardBundlerParam<> (
+            I18N.getString("param.xdg-prefix.name"),
+            I18N.getString("param.xdg-prefix.description"),
+            "linux.xdg-prefix",
+            String.class,
+            params -> {
+                try {
+                    String vendor;
+                    if (params.containsKey(VENDOR.getID())) {
+                        vendor = VENDOR.fetchFrom(params);
+                    } else {
+                        vendor = "jpackager";
+                    }
+                    String appName = APP_FS_NAME.fetchFrom(params);
+
+                    return (appName + "-" + vendor).replaceAll("\\s", "");
+                } catch (Exception e) {
+                    if (Log.isDebug()) {
+                        e.printStackTrace();
+                    }
+                }
+                return "unknown-MimeInfo.xml";
+            },
+            (s, p) -> s);
+
+    private final static String DEFAULT_ICON = "javalogo_white_32.png";
+    private final static String DEFAULT_CONTROL_TEMPLATE = "template.control";
+    private final static String DEFAULT_PRERM_TEMPLATE = "template.prerm";
+    private final static String DEFAULT_PREINSTALL_TEMPLATE =
+            "template.preinst";
+    private final static String DEFAULT_POSTRM_TEMPLATE = "template.postrm";
+    private final static String DEFAULT_POSTINSTALL_TEMPLATE =
+            "template.postinst";
+    private final static String DEFAULT_COPYRIGHT_TEMPLATE =
+            "template.copyright";
+    private final static String DEFAULT_DESKTOP_FILE_TEMPLATE =
+            "template.desktop";
+
+    public final static String TOOL_DPKG = "dpkg-deb";
+
+    public LinuxDebBundler() {
+        super();
+        baseResourceLoader = LinuxResources.class;
+    }
+
+    public static boolean testTool(String toolName, String minVersion) {
+        try {
+            ProcessBuilder pb = new ProcessBuilder(
+                    toolName,
+                    "--version");
+            // not interested in the output
+            IOUtils.exec(pb, Log.isDebug(), true);
+        } catch (Exception e) {
+            Log.verbose(MessageFormat.format(I18N.getString(
+                    "message.test-for-tool"), toolName, e.getMessage()));
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> p)
+            throws UnsupportedPlatformException, ConfigException {
+        try {
+            if (p == null) throw new ConfigException(
+                    I18N.getString("error.parameters-null"),
+                    I18N.getString("error.parameters-null.advice"));
+
+            //run basic validation to ensure requirements are met
+            //we are not interested in return code, only possible exception
+            APP_BUNDLER.fetchFrom(p).doValidate(p);
+
+            // NOTE: Can we validate that the required tools are available
+            // before we start?
+            if (!testTool(TOOL_DPKG, "1")){
+                throw new ConfigException(MessageFormat.format(
+                        I18N.getString("error.tool-not-found"), TOOL_DPKG),
+                        I18N.getString("error.tool-not-found.advice"));
+            }
+
+
+            // validate license file, if used, exists in the proper place
+            if (p.containsKey(LICENSE_FILE.getID())) {
+                List<RelativeFileSet> appResourcesList =
+                        APP_RESOURCES_LIST.fetchFrom(p);
+                for (String license : LICENSE_FILE.fetchFrom(p)) {
+                    boolean found = false;
+                    for (RelativeFileSet appResources : appResourcesList) {
+                        found = found || appResources.contains(license);
+                    }
+                    if (!found) {
+                        throw new ConfigException(
+                                I18N.getString("error.license-missing"),
+                                MessageFormat.format(I18N.getString(
+                                        "error.license-missing.advice"),
+                                        license));
+                    }
+                }
+            } else {
+                Log.info(I18N.getString("message.debs-like-licenses"));
+            }
+
+            // only one mime type per association, at least one file extention
+            List<Map<String, ? super Object>> associations =
+                    FILE_ASSOCIATIONS.fetchFrom(p);
+            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 == null || mimes.isEmpty()) {
+                        String msgKey =
+                            "error.no-content-types-for-file-association";
+                        throw new ConfigException(
+                                MessageFormat.format(I18N.getString(msgKey), i),
+                                I18N.getString(msgKey + ".advise"));
+                        
+                    } else if (mimes.size() > 1) {
+                        String msgKey =
+                            "error.too-many-content-types-for-file-association";
+                        throw new ConfigException(
+                                MessageFormat.format(I18N.getString(msgKey), i),
+                                I18N.getString(msgKey + ".advise"));
+                    }
+                }
+            }
+
+            // bundle name has some restrictions
+            // the string converter will throw an exception if invalid
+            BUNDLE_NAME.getStringConverter().apply(BUNDLE_NAME.fetchFrom(p), p);
+
+            return true;
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    private boolean prepareProto(Map<String, ? super Object> p) {
+        File appDir = StandardBundlerParam.getPredefinedAppImage(p);
+        if (appDir == null) {
+            appDir = APP_BUNDLER.fetchFrom(p).doBundle(p,
+                    APP_IMAGE_ROOT.fetchFrom(p), true);
+        }
+        return appDir != null;
+    }
+
+    //@Override
+    public File bundle(Map<String, ? super Object> p, File outdir) {
+        if (!outdir.isDirectory() && !outdir.mkdirs()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-create-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+        if (!outdir.canWrite()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-write-to-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+
+        //we want to create following structure
+        //   <package-name>
+        //        DEBIAN
+        //          control   (file with main package details)
+        //          menu      (request to create menu)
+        //          ... other control files if needed ....
+        //        opt  (by default)
+        //          AppFolder (this is where app image goes)
+        //             launcher executable
+        //             app
+        //             runtime
+
+        File imageDir = DEB_IMAGE_DIR.fetchFrom(p);
+        File configDir = CONFIG_DIR.fetchFrom(p);
+
+        try {
+
+            imageDir.mkdirs();
+            configDir.mkdirs();
+            if (prepareProto(p) && prepareProjectConfig(p)) {
+                return buildDeb(p, outdir);
+            }
+            return null;
+        } catch (IOException ex) {
+            ex.printStackTrace();
+            return null;
+        } finally {
+            try {
+                if (ECHO_MODE.fetchFrom(p)) {
+                    saveConfigFiles(p);
+                }
+                if (imageDir != null &&
+                        PREDEFINED_APP_IMAGE.fetchFrom(p) == null &&
+                        (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ||
+                        !Arguments.CREATE_JRE_INSTALLER.fetchFrom(p)) &&
+                        !Log.isDebug()) {
+                    IOUtils.deleteRecursive(imageDir);
+                } else if (imageDir != null) {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "message.debug-working-directory"),
+                            imageDir.getAbsolutePath()));
+                }
+            } catch (IOException ex) {
+                //noinspection ReturnInsideFinallyBlock
+                Log.debug(ex.getMessage());
+                return null;
+            }
+        }
+    }
+
+    /*
+     * set permissions with a string like "rwxr-xr-x"
+     *
+     * This cannot be directly backport to 22u which is unfortunately 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) {
+            Logger.getLogger(LinuxDebBundler.class.getName()).log(
+                    Level.SEVERE, null, ex);
+        }
+
+    }
+
+    protected void saveConfigFiles(Map<String, ? super Object> params) {
+        try {
+            File configRoot = CONFIG_ROOT.fetchFrom(params);
+            File rootDir = LinuxAppBundler.getRootDir(
+                    APP_IMAGE_ROOT.fetchFrom(params), params);
+
+            if (getConfig_ControlFile(params).exists()) {
+                IOUtils.copyFile(getConfig_ControlFile(params),
+                        new File(configRoot,
+                        getConfig_ControlFile(params).getName()));
+            }
+            if (getConfig_CopyrightFile(params).exists()) {
+                IOUtils.copyFile(getConfig_CopyrightFile(params),
+                        new File(configRoot,
+                                getConfig_CopyrightFile(params).getName()));
+            }
+            if (getConfig_PreinstallFile(params).exists()) {
+                IOUtils.copyFile(getConfig_PreinstallFile(params),
+                        new File(configRoot,
+                                getConfig_PreinstallFile(params).getName()));
+            }
+            if (getConfig_PrermFile(params).exists()) {
+                IOUtils.copyFile(getConfig_PrermFile(params),
+                        new File(configRoot,
+                                getConfig_PrermFile(params).getName()));
+            }
+            if (getConfig_PostinstallFile(params).exists()) {
+                IOUtils.copyFile(getConfig_PostinstallFile(params),
+                        new File(configRoot,
+                                getConfig_PostinstallFile(params).getName()));
+            }
+            if (getConfig_PostrmFile(params).exists()) {
+                IOUtils.copyFile(getConfig_PostrmFile(params),
+                        new File(configRoot,
+                                getConfig_PostrmFile(params).getName()));
+            }
+            if (getConfig_DesktopShortcutFile(rootDir, params).exists()) {
+                IOUtils.copyFile(getConfig_DesktopShortcutFile(rootDir, params),
+                        new File(configRoot,
+                                getConfig_DesktopShortcutFile(rootDir,
+                                        params).getName()));
+            }
+            for (Map<String, ? super Object> secondaryLauncher :
+                    SECONDARY_LAUNCHERS.fetchFrom(params)) {
+                if (getConfig_DesktopShortcutFile(rootDir,
+                        secondaryLauncher).exists()) {
+                    IOUtils.copyFile(
+                            getConfig_DesktopShortcutFile(rootDir,
+                            secondaryLauncher),
+                            new File(configRoot, getConfig_DesktopShortcutFile(
+                            rootDir, secondaryLauncher).getName()));
+                }
+            }
+            if (getConfig_IconFile(rootDir, params).exists()) {
+                IOUtils.copyFile(getConfig_IconFile(rootDir, params),
+                        new File(configRoot,
+                                getConfig_IconFile(rootDir, params).getName()));
+            }
+            Log.info(MessageFormat.format(
+                    I18N.getString("message.config-save-location"),
+                    configRoot.getAbsolutePath()));
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        }
+    }
+
+    private String getArch() {
+        String arch = System.getProperty("os.arch");
+        if ("i386".equals(arch))
+            return "i386";
+        else
+            return "amd64";
+    }
+
+    private long getInstalledSizeKB(Map<String, ? super Object> params) {
+        return getInstalledSizeKB(APP_IMAGE_ROOT.fetchFrom(params)) >> 10;
+    }
+
+    private long getInstalledSizeKB(File dir) {
+        long count = 0;
+        File[] children = dir.listFiles();
+        if (children != null) {
+            for (File file : children) {
+                if (file.isFile()) {
+                    count += file.length();
+                }
+                else if (file.isDirectory()) {
+                    count += getInstalledSizeKB(file);
+                }
+            }
+        }
+        return count;
+    }
+
+    private boolean prepareProjectConfig(Map<String, ? super Object> params)
+            throws IOException {
+        Map<String, String> data = createReplacementData(params);
+        File rootDir = LinuxAppBundler.getRootDir(APP_IMAGE_ROOT.fetchFrom(
+                params), params);
+        
+        File iconTarget = getConfig_IconFile(rootDir, params);
+        File icon = ICON_PNG.fetchFrom(params);
+        if (!Arguments.CREATE_JRE_INSTALLER.fetchFrom(params)) {
+            //  prepare installer icon
+            if (icon == null || !icon.exists()) {
+                fetchResource(LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + iconTarget.getName(),
+                        I18N.getString("resource.menu-icon"),
+                        DEFAULT_ICON,
+                        iconTarget,
+                        VERBOSE.fetchFrom(params),
+                        DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            } else {
+                fetchResource(LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + iconTarget.getName(),
+                        I18N.getString("resource.menu-icon"),
+                        icon,
+                        iconTarget,
+                        VERBOSE.fetchFrom(params),
+                        DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            }
+        }
+
+        StringBuilder installScripts = new StringBuilder();
+        StringBuilder removeScripts = new StringBuilder();
+        for (Map<String, ? super Object> secondaryLauncher :
+                SECONDARY_LAUNCHERS.fetchFrom(params)) {
+            Map<String, String> secondaryLauncherData =
+                    createReplacementData(secondaryLauncher);
+            secondaryLauncherData.put("APPLICATION_FS_NAME",
+                    data.get("APPLICATION_FS_NAME"));
+            secondaryLauncherData.put("DESKTOP_MIMES", "");
+
+            if (!Arguments.CREATE_JRE_INSTALLER.fetchFrom(params)) {
+                // prepare desktop shortcut
+                Writer w = new BufferedWriter(new FileWriter(
+                        getConfig_DesktopShortcutFile(
+                                rootDir, secondaryLauncher)));
+                String content = preprocessTextResource(
+                        LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                                + getConfig_DesktopShortcutFile(rootDir,
+                                        secondaryLauncher).getName(),
+                        I18N.getString("resource.menu-shortcut-descriptor"),
+                        DEFAULT_DESKTOP_FILE_TEMPLATE,
+                        secondaryLauncherData,
+                        VERBOSE.fetchFrom(params),
+                        DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+                w.write(content);
+                w.close();
+            }
+
+            //prepare installer icon
+            iconTarget = getConfig_IconFile(rootDir, secondaryLauncher);
+            icon = ICON_PNG.fetchFrom(secondaryLauncher);
+            if (icon == null || !icon.exists()) {
+                fetchResource(LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + iconTarget.getName(),
+                        I18N.getString("resource.menu-icon"),
+                        DEFAULT_ICON,
+                        iconTarget,
+                        VERBOSE.fetchFrom(params),
+                        DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            } else {
+                fetchResource(LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + iconTarget.getName(),
+                        I18N.getString("resource.menu-icon"),
+                        icon,
+                        iconTarget,
+                        VERBOSE.fetchFrom(params),
+                        DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            }
+
+            //postinst copying of desktop icon
+            installScripts.append(
+                    "        xdg-desktop-menu install --novendor ");
+            installScripts.append(LINUX_INSTALL_DIR.fetchFrom(params));
+            installScripts.append("/");
+            installScripts.append(data.get("APPLICATION_FS_NAME"));
+            installScripts.append("/");
+            installScripts.append(
+                    secondaryLauncherData.get("APPLICATION_LAUNCHER_FILENAME"));
+            installScripts.append(".desktop\n");
+
+            //postrm cleanup of desktop icon
+            removeScripts.append(
+                    "        xdg-desktop-menu uninstall --novendor ");
+            removeScripts.append(LINUX_INSTALL_DIR.fetchFrom(params));
+            removeScripts.append("/");
+            removeScripts.append(data.get("APPLICATION_FS_NAME"));
+            removeScripts.append("/");
+            removeScripts.append(
+                    secondaryLauncherData.get("APPLICATION_LAUNCHER_FILENAME"));
+            removeScripts.append(".desktop\n");
+        }
+        data.put("SECONDARY_LAUNCHERS_INSTALL", installScripts.toString());
+        data.put("SECONDARY_LAUNCHERS_REMOVE", removeScripts.toString());
+
+        List<Map<String, ? super Object>> associations =
+                FILE_ASSOCIATIONS.fetchFrom(params);
+        data.put("FILE_ASSOCIATION_INSTALL", "");
+        data.put("FILE_ASSOCIATION_REMOVE", "");
+        data.put("DESKTOP_MIMES", "");
+        if (associations != null) {
+            String mimeInfoFile = XDG_FILE_PREFIX.fetchFrom(params)
+                    + "-MimeInfo.xml";
+            StringBuilder mimeInfo = new StringBuilder(
+                "<?xml version=\"1.0\"?>\n<mime-info xmlns="
+                + "'http://www.freedesktop.org/standards/shared-mime-info'>\n");
+            StringBuilder registrations = new StringBuilder();
+            StringBuilder deregistrations = new StringBuilder();
+            StringBuilder desktopMimes = new StringBuilder("MimeType=");
+            boolean addedEntry = false;
+
+            for (Map<String, ? super Object> assoc : associations) {
+                //  <mime-type type="application/x-vnd.awesome">
+                //    <comment>Awesome document</comment>
+                //    <glob pattern="*.awesome"/>
+                //    <glob pattern="*.awe"/>
+                //  </mime-type>
+
+                if (assoc == null) {
+                    continue;
+                }
+
+                String description = FA_DESCRIPTION.fetchFrom(assoc);
+                File faIcon = FA_ICON.fetchFrom(assoc); //TODO FA_ICON_PNG
+                List<String> extensions = FA_EXTENSIONS.fetchFrom(assoc);
+                if (extensions == null) {
+                    Log.info(I18N.getString(
+                            "message.creating-association-with-null-extension"));
+                }
+
+                List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc);
+                if (mimes == null || mimes.isEmpty()) {
+                    continue;
+                }
+                String thisMime = mimes.get(0);
+                String dashMime = thisMime.replace('/', '-');
+
+                mimeInfo.append("  <mime-type type='")
+                        .append(thisMime)
+                        .append("'>\n");
+                if (description != null && !description.isEmpty()) {
+                    mimeInfo.append("    <comment>")
+                            .append(description)
+                            .append("</comment>\n");
+                }
+
+                if (extensions != null) {
+                    for (String ext : extensions) {
+                        mimeInfo.append("    <glob pattern='*.")
+                                .append(ext)
+                                .append("'/>\n");
+                    }
+                }
+
+                mimeInfo.append("  </mime-type>\n");
+                if (!addedEntry) {
+                    registrations.append("        xdg-mime install ")
+                            .append(LINUX_INSTALL_DIR.fetchFrom(params))
+                            .append("/")
+                            .append(data.get("APPLICATION_FS_NAME"))
+                            .append("/")
+                            .append(mimeInfoFile)
+                            .append("\n");
+
+                    deregistrations.append("        xdg-mime uninstall ")
+                            .append(LINUX_INSTALL_DIR.fetchFrom(params))
+                            .append("/")
+                            .append(data.get("APPLICATION_FS_NAME"))
+                            .append("/")
+                            .append(mimeInfoFile)
+                            .append("\n");
+                    addedEntry = true;
+                } else {
+                    desktopMimes.append(";");
+                }
+                desktopMimes.append(thisMime);
+
+                if (faIcon != null && faIcon.exists()) {
+                    int size = getSquareSizeOfImage(faIcon);
+
+                    if (size > 0) {
+                        File target = new File(rootDir,
+                                APP_FS_NAME.fetchFrom(params)
+                                + "_fa_" + faIcon.getName());
+                        IOUtils.copyFile(faIcon, target);
+
+                        // xdg-icon-resource install --context mimetypes
+                        // --size 64 awesomeapp_fa_1.png
+                        // application-x.vnd-awesome
+                        registrations.append(
+                                "        xdg-icon-resource install "
+                                        + "--context mimetypes --size ")
+                                .append(size)
+                                .append(" ")
+                                .append(LINUX_INSTALL_DIR.fetchFrom(params))
+                                .append("/")
+                                .append(data.get("APPLICATION_FS_NAME"))
+                                .append("/")
+                                .append(target.getName())
+                                .append(" ")
+                                .append(dashMime)
+                                .append("\n");
+
+                        //x dg-icon-resource uninstall --context mimetypes
+                        // --size 64 awesomeapp_fa_1.png
+                        // application-x.vnd-awesome
+                        deregistrations.append(
+                                "        xdg-icon-resource uninstall "
+                                        + "--context mimetypes --size ")
+                                .append(size)
+                                .append(" ")
+                                .append(LINUX_INSTALL_DIR.fetchFrom(params))
+                                .append("/")
+                                .append(data.get("APPLICATION_FS_NAME"))
+                                .append("/")
+                                .append(target.getName())
+                                .append(" ")
+                                .append(dashMime)
+                                .append("\n");
+                    }
+                }
+            }
+            mimeInfo.append("</mime-info>");
+
+            if (addedEntry) {
+                Writer w = new BufferedWriter(new FileWriter(
+                        new File(rootDir, mimeInfoFile)));
+                w.write(mimeInfo.toString());
+                w.close();
+                data.put("FILE_ASSOCIATION_INSTALL", registrations.toString());
+                data.put("FILE_ASSOCIATION_REMOVE", deregistrations.toString());
+                data.put("DESKTOP_MIMES", desktopMimes.toString());
+            }
+        }
+        
+        if (!Arguments.CREATE_JRE_INSTALLER.fetchFrom(params)) {
+            //prepare desktop shortcut
+            Writer w = new BufferedWriter(new FileWriter(
+                    getConfig_DesktopShortcutFile(rootDir, params)));
+            String content = preprocessTextResource(
+                    LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                            + getConfig_DesktopShortcutFile(
+                                    rootDir, params).getName(),
+                    I18N.getString("resource.menu-shortcut-descriptor"),
+                    DEFAULT_DESKTOP_FILE_TEMPLATE,
+                    data,
+                    VERBOSE.fetchFrom(params),
+                    DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            w.write(content);
+            w.close();
+        }
+        //prepare control file
+        Writer w = new BufferedWriter(new FileWriter(
+                getConfig_ControlFile(params)));
+        String content = preprocessTextResource(
+                LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + getConfig_ControlFile(params).getName(),
+                I18N.getString("resource.deb-control-file"),
+                DEFAULT_CONTROL_TEMPLATE,
+                data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        w.write(content);
+        w.close();
+
+        w = new BufferedWriter(new FileWriter(
+                getConfig_PreinstallFile(params)));
+        content = preprocessTextResource(
+                LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + getConfig_PreinstallFile(params).getName(),
+                I18N.getString("resource.deb-preinstall-script"),
+                DEFAULT_PREINSTALL_TEMPLATE,
+                data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        w.write(content);
+        w.close();
+        setPermissions(getConfig_PreinstallFile(params), "rwxr-xr-x");
+
+        w = new BufferedWriter(new FileWriter(getConfig_PrermFile(params)));
+        content = preprocessTextResource(
+                LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + getConfig_PrermFile(params).getName(),
+                I18N.getString("resource.deb-prerm-script"),
+                DEFAULT_PRERM_TEMPLATE,
+                data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        w.write(content);
+        w.close();
+        setPermissions(getConfig_PrermFile(params), "rwxr-xr-x");
+
+        w = new BufferedWriter(new FileWriter(getConfig_PostinstallFile(params)));
+        content = preprocessTextResource(
+                LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + getConfig_PostinstallFile(params).getName(),
+                I18N.getString("resource.deb-postinstall-script"),
+                DEFAULT_POSTINSTALL_TEMPLATE,
+                data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        w.write(content);
+        w.close();
+        setPermissions(getConfig_PostinstallFile(params), "rwxr-xr-x");
+
+        w = new BufferedWriter(new FileWriter(getConfig_PostrmFile(params)));
+        content = preprocessTextResource(
+                LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + getConfig_PostrmFile(params).getName(),
+                I18N.getString("resource.deb-postrm-script"),
+                DEFAULT_POSTRM_TEMPLATE,
+                data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        w.write(content);
+        w.close();
+        setPermissions(getConfig_PostrmFile(params), "rwxr-xr-x");
+
+        w = new BufferedWriter(new FileWriter(getConfig_CopyrightFile(params)));
+        content = preprocessTextResource(
+                LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + getConfig_CopyrightFile(params).getName(),
+                I18N.getString("resource.deb-copyright-file"),
+                DEFAULT_COPYRIGHT_TEMPLATE,
+                data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        w.write(content);
+        w.close();
+
+        return true;
+    }
+
+    private Map<String, String> createReplacementData(
+            Map<String, ? super Object> params) {
+        Map<String, String> data = new HashMap<>();
+
+        data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
+        data.put("APPLICATION_FS_NAME", APP_FS_NAME.fetchFrom(params));
+        data.put("APPLICATION_PACKAGE", BUNDLE_NAME.fetchFrom(params));
+        data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
+        data.put("APPLICATION_MAINTAINER", MAINTAINER.fetchFrom(params));
+        data.put("APPLICATION_VERSION", VERSION.fetchFrom(params));
+        data.put("APPLICATION_LAUNCHER_FILENAME",
+                APP_FS_NAME.fetchFrom(params));
+        data.put("INSTALLATION_DIRECTORY", LINUX_INSTALL_DIR.fetchFrom(params));
+        data.put("XDG_PREFIX", XDG_FILE_PREFIX.fetchFrom(params));
+        data.put("DEPLOY_BUNDLE_CATEGORY", CATEGORY.fetchFrom(params));
+        data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
+        data.put("APPLICATION_SUMMARY", TITLE.fetchFrom(params));
+        data.put("APPLICATION_COPYRIGHT", COPYRIGHT.fetchFrom(params));
+        data.put("APPLICATION_LICENSE_TEXT", LICENSE_TEXT.fetchFrom(params));
+        data.put("APPLICATION_ARCH", getArch());
+        data.put("APPLICATION_INSTALLED_SIZE",
+                Long.toString(getInstalledSizeKB(params)));
+        String deps = LINUX_PACKAGE_DEPENDENCIES.fetchFrom(params);
+        data.put("PACKAGE_DEPENDENCIES",
+                deps.isEmpty() ? "" : "Depends: " + deps);
+        data.put("CREATE_JRE_INSTALLER",
+                Arguments.CREATE_JRE_INSTALLER.fetchFrom(params).toString());
+        
+        return data;
+    }
+
+    private File getConfig_DesktopShortcutFile(File rootDir,
+            Map<String, ? super Object> params) {
+        return new File(rootDir,
+                APP_FS_NAME.fetchFrom(params) + ".desktop");
+    }
+
+    private File getConfig_IconFile(File rootDir,
+            Map<String, ? super Object> params) {
+        return new File(rootDir,
+                APP_FS_NAME.fetchFrom(params) + ".png");
+    }
+
+    private File getConfig_InitScriptFile(Map<String, ? super Object> params) {
+        return new File(LinuxAppBundler.getRootDir(
+                APP_IMAGE_ROOT.fetchFrom(params), params),
+                        BUNDLE_NAME.fetchFrom(params) + ".init");
+    }
+
+    private File getConfig_ControlFile(Map<String, ? super Object> params) {
+        return new File(CONFIG_DIR.fetchFrom(params), "control");
+    }
+
+    private File getConfig_PreinstallFile(Map<String, ? super Object> params) {
+        return new File(CONFIG_DIR.fetchFrom(params), "preinst");
+    }
+
+    private File getConfig_PrermFile(Map<String, ? super Object> params) {
+        return new File(CONFIG_DIR.fetchFrom(params), "prerm");
+    }
+
+    private File getConfig_PostinstallFile(Map<String, ? super Object> params) {
+        return new File(CONFIG_DIR.fetchFrom(params), "postinst");
+    }
+
+    private File getConfig_PostrmFile(Map<String, ? super Object> params) {
+        return new File(CONFIG_DIR.fetchFrom(params), "postrm");
+    }
+
+    private File getConfig_CopyrightFile(Map<String, ? super Object> params) {
+        return new File(CONFIG_DIR.fetchFrom(params), "copyright");
+    }
+
+    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()));
+
+        outFile.getParentFile().mkdirs();
+
+        //run dpkg
+        ProcessBuilder pb = new ProcessBuilder(
+                "fakeroot", TOOL_DPKG, "-b",
+                FULL_PACKAGE_NAME.fetchFrom(params),
+                outFile.getAbsolutePath());
+        pb = pb.directory(DEB_IMAGE_DIR.fetchFrom(params).getParentFile());
+        IOUtils.exec(pb, ECHO_MODE.fetchFrom(params));
+
+        Log.info(MessageFormat.format(I18N.getString(
+                "message.output-to-location"), outFile.getAbsolutePath()));
+
+        return outFile;
+    }
+
+    @Override
+    public String getName() {
+        return I18N.getString("bundler.name");
+    }
+
+    @Override
+    public String getDescription() {
+        return I18N.getString("bundler.description");
+    }
+
+    @Override
+    public String getID() {
+        return "deb";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "INSTALLER";
+    }
+
+    @Override
+    public Collection<BundlerParamInfo<?>> getBundleParameters() {
+        Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
+        results.addAll(LinuxAppBundler.getAppBundleParameters());
+        results.addAll(getDebBundleParameters());
+        return results;
+    }
+
+    public static Collection<BundlerParamInfo<?>> getDebBundleParameters() {
+        return Arrays.asList(
+                BUNDLE_NAME,
+                COPYRIGHT,
+                CATEGORY,
+                DESCRIPTION,
+                EMAIL,
+                ICON_PNG,
+                LICENSE_FILE,
+                TITLE,
+                VENDOR
+        );
+    }
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) {
+        return bundle(params, outputParentDir);
+    }
+    
+    @Override    
+    public boolean supported() {
+        return (Platform.getPlatform() == Platform.LINUX);
+    }
+
+    public int getSquareSizeOfImage(File f) {
+        try {
+            BufferedImage bi = ImageIO.read(f);
+            if (bi.getWidth() == bi.getHeight()) {
+                return bi.getWidth();
+            } else {
+                return 0;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/linux/LinuxRpmBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,829 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.linux;
+
+import jdk.packager.internal.*;
+import jdk.packager.internal.Arguments;
+import jdk.packager.internal.resources.linux.LinuxResources;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static jdk.packager.internal.StandardBundlerParam.*;
+import static jdk.packager.internal.linux.LinuxAppBundler.LINUX_INSTALL_DIR;
+import static
+        jdk.packager.internal.linux.LinuxAppBundler.LINUX_PACKAGE_DEPENDENCIES;
+
+public class LinuxRpmBundler extends AbstractBundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.linux.LinuxRpmBundler");
+
+    public static final BundlerParamInfo<LinuxAppBundler> APP_BUNDLER = 
+            new StandardBundlerParam<>(
+            I18N.getString("param.app-bundler.name"),
+            I18N.getString("param.app-bundler.description"),
+            "linux.app.bundler",
+            LinuxAppBundler.class,
+            params -> new LinuxAppBundler(),
+            null);
+
+    public static final BundlerParamInfo<File> RPM_IMAGE_DIR =
+            new StandardBundlerParam<>(
+            I18N.getString("param.image-dir.name"),
+            I18N.getString("param.image-dir.description"),
+            "linux.rpm.imageDir",
+            File.class,
+            params -> {
+                File imagesRoot = IMAGES_ROOT.fetchFrom(params);
+                if (!imagesRoot.exists()) imagesRoot.mkdirs();
+                return new File(imagesRoot, "linux-rpm.image");
+            },
+            (s, p) -> new File(s));
+
+    public static final BundlerParamInfo<File> CONFIG_ROOT =
+            new StandardBundlerParam<>(
+            I18N.getString("param.config-root.name"),
+            I18N.getString("param.config-root.description"),
+            "configRoot",
+            File.class,
+            params ->  new File(BUILD_ROOT.fetchFrom(params), "linux"),
+            (s, p) -> new File(s));
+
+    // 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_BUNDLE_NAME_PATTERN =
+            Pattern.compile("[a-z\\d\\+\\-\\.\\_]+", Pattern.CASE_INSENSITIVE);
+
+    public static final BundlerParamInfo<String> BUNDLE_NAME =
+            new StandardBundlerParam<> (
+            I18N.getString("param.bundle-name.name"),
+            I18N.getString("param.bundle-name.description"),
+            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_BUNDLE_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<>(
+                I18N.getString("param.license-type.name"),
+                I18N.getString("param.license-type.description"),
+                Arguments.CLIOptions.LINUX_RPM_LICENSE_TYPE.getId(),
+                String.class,
+                params -> I18N.getString("param.license-type.default"),
+                (s, p) -> s
+        );
+
+    public static final BundlerParamInfo<String> XDG_FILE_PREFIX =
+            new StandardBundlerParam<> (
+            I18N.getString("param.xdg-prefix.name"),
+            I18N.getString("param.xdg-prefix.description"),
+            "linux.xdg-prefix",
+            String.class,
+            params -> {
+                try {
+                    String vendor;
+                    if (params.containsKey(VENDOR.getID())) {
+                        vendor = VENDOR.fetchFrom(params);
+                    } else {
+                        vendor = "javapackager";
+                    }
+                    String appName = APP_FS_NAME.fetchFrom(params);
+
+                    return (vendor + "-" + appName).replaceAll("\\s", "");
+                } catch (Exception e) {
+                    if (Log.isDebug()) {
+                        e.printStackTrace();
+                    }
+                }
+                return "unknown-MimeInfo.xml";
+            },
+            (s, p) -> s);
+
+    private final static String DEFAULT_ICON = "javalogo_white_32.png";
+    private final static String DEFAULT_SPEC_TEMPLATE = "template.spec";
+    private final static String DEFAULT_DESKTOP_FILE_TEMPLATE = "template.desktop";
+
+    public final static String TOOL_RPMBUILD = "rpmbuild";
+    public final static double TOOL_RPMBUILD_MIN_VERSION = 4.0d;
+
+    public LinuxRpmBundler() {
+        super();
+        baseResourceLoader = LinuxResources.class;
+    }
+
+    public static boolean testTool(String toolName, double minVersion) {
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                PrintStream ps = new PrintStream(baos)) {
+            ProcessBuilder pb = new ProcessBuilder(toolName, "--version");
+            IOUtils.exec(pb, Log.isDebug(), false, ps); 
+                    //not interested in the above's output
+            String content = new String(baos.toByteArray());
+            Pattern pattern = Pattern.compile(" (\\d+\\.\\d+)");
+            Matcher matcher = pattern.matcher(content);
+
+            if (matcher.find()) {
+                String v = matcher.group(1);
+                double version = new Double(v);
+                return minVersion <= version;
+            } else {
+               return false;
+            }
+        } catch (Exception e) {
+            Log.verbose(MessageFormat.format(I18N.getString(
+                    "message.test-for-tool"), toolName, e.getMessage()));
+            return false;
+        }
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> p)
+            throws UnsupportedPlatformException, ConfigException {
+        try {
+            if (p == null) throw new ConfigException(
+                    I18N.getString("error.parameters-null"),
+                    I18N.getString("error.parameters-null.advice"));
+
+            //run basic validation to ensure requirements are met
+            //we are not interested in return code, only possible exception
+            APP_BUNDLER.fetchFrom(p).doValidate(p);
+
+            // validate license file, if used, exists in the proper place
+            if (p.containsKey(LICENSE_FILE.getID())) {
+                List<RelativeFileSet> appResourcesList =
+                        APP_RESOURCES_LIST.fetchFrom(p);
+                for (String license : LICENSE_FILE.fetchFrom(p)) {
+                    boolean found = false;
+                    for (RelativeFileSet appResources : appResourcesList) {
+                        found = found || appResources.contains(license);
+                    }
+                    if (!found) {
+                        throw new ConfigException(
+                                I18N.getString("error.license-missing"),
+                                MessageFormat.format(
+                                I18N.getString("error.license-missing.advice"),
+                                license));
+                    }
+                }
+            }
+
+            //validate presense of required tools
+            if (!testTool(TOOL_RPMBUILD, TOOL_RPMBUILD_MIN_VERSION)){
+                throw new ConfigException(
+                    MessageFormat.format(
+                        I18N.getString("error.cannot-find-rpmbuild"),
+                        TOOL_RPMBUILD_MIN_VERSION),
+                    MessageFormat.format(
+                        I18N.getString("error.cannot-find-rpmbuild.advice"),
+                        TOOL_RPMBUILD_MIN_VERSION));
+            }
+
+            // only one mime type per association, at least one file extension
+            List<Map<String, ? super Object>> associations =
+                    FILE_ASSOCIATIONS.fetchFrom(p);
+            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 == null || mimes.isEmpty()) {
+                        String msgKey =
+                                "error.no-content-types-for-file-association";
+                        throw new ConfigException(
+                                MessageFormat.format(I18N.getString(msgKey), i),
+                                I18N.getString(msgKey + ".advice"));
+                    } else if (mimes.size() > 1) {
+                        String msgKey =
+                                "error.no-content-types-for-file-association";
+                        throw new ConfigException(
+                                MessageFormat.format(I18N.getString(msgKey), i),
+                                I18N.getString(msgKey + ".advice"));
+                    }
+                }
+            }
+
+            // bundle name has some restrictions
+            // the string converter will throw an exception if invalid
+            BUNDLE_NAME.getStringConverter().apply(BUNDLE_NAME.fetchFrom(p), p);
+
+            return true;
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    private boolean prepareProto(Map<String, ? super Object> params) {
+        File appDir = StandardBundlerParam.getPredefinedAppImage(params);
+        if (appDir == null) {
+            appDir = APP_BUNDLER.fetchFrom(params).doBundle(
+                    params, RPM_IMAGE_DIR.fetchFrom(params), true);
+        }
+        return appDir != null;
+    }
+
+    public File bundle(Map<String, ? super Object> p, File outdir) {
+        if (!outdir.isDirectory() && !outdir.mkdirs()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-create-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+        if (!outdir.canWrite()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-write-to-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+
+        File imageDir = RPM_IMAGE_DIR.fetchFrom(p);
+        try {
+
+            imageDir.mkdirs();
+
+            if (prepareProto(p) && prepareProjectConfig(p)) {
+                return buildRPM(p, outdir);
+            }
+            return null;
+        } catch (IOException ex) {
+            ex.printStackTrace();
+            return null;
+        } finally {
+            try {
+                if (ECHO_MODE.fetchFrom(p)) {
+                    saveConfigFiles(p);
+                }
+                if (imageDir != null &&
+                        PREDEFINED_APP_IMAGE.fetchFrom(p) == null &&
+                        (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ||
+                        !Arguments.CREATE_JRE_INSTALLER.fetchFrom(p)) &&
+                        !Log.isDebug()) {
+                    IOUtils.deleteRecursive(imageDir);
+                } else if (imageDir != null) {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "message.debug-working-directory"),
+                            imageDir.getAbsolutePath()));
+                }
+            } catch (IOException ex) {
+                //noinspection ReturnInsideFinallyBlock
+                Log.debug(ex.getMessage());
+                return null;
+            }
+        }
+    }
+
+    /*
+     * 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) {
+            Logger.getLogger(LinuxDebBundler.class.getName()).log(
+                    Level.SEVERE, null, ex);
+        }
+    }
+
+    protected void saveConfigFiles(Map<String, ? super Object> params) {
+        try {
+            File configRoot = CONFIG_ROOT.fetchFrom(params);
+            File rootDir = LinuxAppBundler.getRootDir(
+                    RPM_IMAGE_DIR.fetchFrom(params), params);
+
+            if (getConfig_SpecFile(params).exists()) {
+                IOUtils.copyFile(getConfig_SpecFile(params),
+                        new File(configRoot,
+                                getConfig_SpecFile(params).getName()));
+            }
+            if (getConfig_DesktopShortcutFile(rootDir, params).exists()) {
+                IOUtils.copyFile(getConfig_DesktopShortcutFile(rootDir, params),
+                        new File(configRoot, getConfig_DesktopShortcutFile(
+                                rootDir, params).getName()));
+            }
+            if (getConfig_IconFile(rootDir, params).exists()) {
+                IOUtils.copyFile(getConfig_IconFile(rootDir, params),
+                        new File(configRoot,
+                                getConfig_IconFile(rootDir, params).getName()));
+            }
+
+            Log.info(MessageFormat.format(
+                    I18N.getString("message.config-save-location"),
+                    configRoot.getAbsolutePath()));
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        }
+    }
+
+    private String getLicenseFileString(Map<String, ? super Object> params) {
+        StringBuilder sb = new StringBuilder();
+        for (String f: LICENSE_FILE.fetchFrom(params)) {
+            if (sb.length() != 0) {
+                sb.append("\n");
+            }
+            sb.append("%doc ");
+            sb.append(LINUX_INSTALL_DIR.fetchFrom(params));
+            sb.append("/");
+            sb.append(APP_FS_NAME.fetchFrom(params));
+            sb.append("/app/");
+            sb.append(f);
+        }
+        return sb.toString();
+    }
+
+    private boolean prepareProjectConfig(Map<String, ? super Object> params)
+            throws IOException {
+        Map<String, String> data = createReplacementData(params);
+        File rootDir =
+            LinuxAppBundler.getRootDir(RPM_IMAGE_DIR.fetchFrom(params), params);
+
+        //prepare installer icon
+        File iconTarget = getConfig_IconFile(rootDir, params);
+        File icon = LinuxAppBundler.ICON_PNG.fetchFrom(params);
+        if (!Arguments.CREATE_JRE_INSTALLER.fetchFrom(params)) {
+            if (icon == null || !icon.exists()) {
+                fetchResource(LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + iconTarget.getName(),
+                        I18N.getString("resource.menu-icon"),
+                        DEFAULT_ICON,
+                        iconTarget,
+                        VERBOSE.fetchFrom(params),
+                        DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            } else {
+                fetchResource(LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + iconTarget.getName(),
+                        I18N.getString("resource.menu-icon"),
+                        icon,
+                        iconTarget,
+                        VERBOSE.fetchFrom(params),
+                        DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            }
+        }
+
+        StringBuilder installScripts = new StringBuilder();
+        StringBuilder removeScripts = new StringBuilder();
+        for (Map<String, ? super Object> secondaryLauncher :
+                SECONDARY_LAUNCHERS.fetchFrom(params)) {
+            Map<String, String> secondaryLauncherData =
+                    createReplacementData(secondaryLauncher);
+            secondaryLauncherData.put("APPLICATION_FS_NAME",
+                    data.get("APPLICATION_FS_NAME"));
+            secondaryLauncherData.put("DESKTOP_MIMES", "");
+
+            //prepare desktop shortcut
+            Writer w = new BufferedWriter(new FileWriter(
+                    getConfig_DesktopShortcutFile(rootDir, secondaryLauncher)));
+            String content = preprocessTextResource(
+                    LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                            + getConfig_DesktopShortcutFile(rootDir,
+                                    secondaryLauncher).getName(),
+                    I18N.getString("resource.menu-shortcut-descriptor"),
+                    DEFAULT_DESKTOP_FILE_TEMPLATE, secondaryLauncherData,
+                    VERBOSE.fetchFrom(params),
+                    DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            w.write(content);
+            w.close();
+
+            //prepare installer icon
+            iconTarget = getConfig_IconFile(rootDir, secondaryLauncher);
+            icon = LinuxAppBundler.ICON_PNG.fetchFrom(secondaryLauncher);
+            if (icon == null || !icon.exists()) {
+                fetchResource(LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + iconTarget.getName(),
+                        I18N.getString("resource.menu-icon"),
+                        DEFAULT_ICON,
+                        iconTarget,
+                        VERBOSE.fetchFrom(params),
+                        DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            } else {
+                fetchResource(LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + iconTarget.getName(),
+                        I18N.getString("resource.menu-icon"),
+                        icon,
+                        iconTarget,
+                        VERBOSE.fetchFrom(params),
+                        DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            }
+
+            //post copying of desktop icon
+            installScripts.append("xdg-desktop-menu install --novendor ");
+            installScripts.append(LINUX_INSTALL_DIR.fetchFrom(params));
+            installScripts.append("/");
+            installScripts.append(data.get("APPLICATION_FS_NAME"));
+            installScripts.append("/");
+            installScripts.append(secondaryLauncherData.get(
+                    "APPLICATION_LAUNCHER_FILENAME"));
+            installScripts.append(".desktop\n");
+
+            //preun cleanup of desktop icon
+            removeScripts.append("xdg-desktop-menu uninstall --novendor ");
+            removeScripts.append(LINUX_INSTALL_DIR.fetchFrom(params));
+            removeScripts.append("/");
+            removeScripts.append(data.get("APPLICATION_FS_NAME"));
+            removeScripts.append("/");
+            removeScripts.append(secondaryLauncherData.get(
+                    "APPLICATION_LAUNCHER_FILENAME"));
+            removeScripts.append(".desktop\n");
+
+        }
+        data.put("SECONDARY_LAUNCHERS_INSTALL", installScripts.toString());
+        data.put("SECONDARY_LAUNCHERS_REMOVE", removeScripts.toString());
+
+        StringBuilder cdsScript = new StringBuilder();
+
+        data.put("APP_CDS_CACHE", cdsScript.toString());
+
+        List<Map<String, ? super Object>> associations =
+                FILE_ASSOCIATIONS.fetchFrom(params);
+        data.put("FILE_ASSOCIATION_INSTALL", "");
+        data.put("FILE_ASSOCIATION_REMOVE", "");
+        data.put("DESKTOP_MIMES", "");
+        if (associations != null) {
+            String mimeInfoFile = XDG_FILE_PREFIX.fetchFrom(params)
+                    + "-MimeInfo.xml";
+            StringBuilder mimeInfo = new StringBuilder(
+                "<?xml version=\"1.0\"?>\n<mime-info xmlns="
+                +"'http://www.freedesktop.org/standards/shared-mime-info'>\n");
+            StringBuilder registrations = new StringBuilder();
+            StringBuilder deregistrations = new StringBuilder();
+            StringBuilder desktopMimes = new StringBuilder("MimeType=");
+            boolean addedEntry = false;
+
+            for (Map<String, ? super Object> assoc : associations) {
+                //  <mime-type type="application/x-vnd.awesome">
+                //    <comment>Awesome document</comment>
+                //    <glob pattern="*.awesome"/>
+                //    <glob pattern="*.awe"/>
+                //  </mime-type>
+
+                if (assoc == null) {
+                    continue;
+                }
+
+                String description = FA_DESCRIPTION.fetchFrom(assoc);
+                File faIcon = FA_ICON.fetchFrom(assoc); //TODO FA_ICON_PNG
+                List<String> extensions = FA_EXTENSIONS.fetchFrom(assoc);
+                if (extensions == null) {
+                    Log.info(I18N.getString(
+                        "message.creating-association-with-null-extension"));
+                }
+
+                List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc);
+                if (mimes == null || mimes.isEmpty()) {
+                    continue;
+                }
+                String thisMime = mimes.get(0);
+                String dashMime = thisMime.replace('/', '-');
+
+                mimeInfo.append("  <mime-type type='")
+                        .append(thisMime)
+                        .append("'>\n");
+                if (description != null && !description.isEmpty()) {
+                    mimeInfo.append("    <comment>")
+                            .append(description)
+                            .append("</comment>\n");
+                }
+
+                if (extensions != null) {
+                    for (String ext : extensions) {
+                        mimeInfo.append("    <glob pattern='*.")
+                                .append(ext)
+                                .append("'/>\n");
+                    }
+                }
+
+                mimeInfo.append("  </mime-type>\n");
+                if (!addedEntry) {
+                    registrations.append("xdg-mime install ")
+                            .append(LINUX_INSTALL_DIR.fetchFrom(params))
+                            .append("/")
+                            .append(data.get("APPLICATION_FS_NAME"))
+                            .append("/")
+                            .append(mimeInfoFile)
+                            .append("\n");
+
+                    deregistrations.append("xdg-mime uninstall ")
+                            .append(LINUX_INSTALL_DIR.fetchFrom(params))
+                            .append("/")
+                            .append(data.get("APPLICATION_FS_NAME"))
+                            .append("/")
+                            .append(mimeInfoFile)
+                            .append("\n");
+                    addedEntry = true;
+                } else {
+                    desktopMimes.append(";");
+                }
+                desktopMimes.append(thisMime);
+
+                if (faIcon != null && faIcon.exists()) {
+                    int size = getSquareSizeOfImage(faIcon);
+
+                    if (size > 0) {
+                        File target = new File(rootDir,
+                                APP_FS_NAME.fetchFrom(params)
+                                        + "_fa_" + faIcon.getName());
+                        IOUtils.copyFile(faIcon, target);
+
+                        // xdg-icon-resource install --context mimetypes
+                        // --size 64 awesomeapp_fa_1.png
+                        // application-x.vnd-awesome
+                        registrations.append(
+                                "xdg-icon-resource install --context mimetypes --size ")
+                                .append(size)
+                                .append(" ")
+                                .append(LINUX_INSTALL_DIR.fetchFrom(params))
+                                .append("/")
+                                .append(data.get("APPLICATION_FS_NAME"))
+                                .append("/")
+                                .append(target.getName())
+                                .append(" ")
+                                .append(dashMime)
+                                .append("\n");
+
+                        // xdg-icon-resource uninstall --context mimetypes
+                        // --size 64 awesomeapp_fa_1.png
+                        // application-x.vnd-awesome
+                        deregistrations.append(
+                                "xdg-icon-resource uninstall --context mimetypes --size ")
+                                .append(size)
+                                .append(" ")
+                                .append(LINUX_INSTALL_DIR.fetchFrom(params))
+                                .append("/")
+                                .append(data.get("APPLICATION_FS_NAME"))
+                                .append("/")
+                                .append(target.getName())
+                                .append(" ")
+                                .append(dashMime)
+                                .append("\n");
+                    }
+                }
+            }
+            mimeInfo.append("</mime-info>");
+
+            if (addedEntry) {
+                Writer w = new BufferedWriter(new FileWriter(
+                        new File(rootDir, mimeInfoFile)));
+                w.write(mimeInfo.toString());
+                w.close();
+                data.put("FILE_ASSOCIATION_INSTALL", registrations.toString());
+                data.put("FILE_ASSOCIATION_REMOVE", deregistrations.toString());
+                data.put("DESKTOP_MIMES", desktopMimes.toString());
+            }
+        }
+
+        if (!Arguments.CREATE_JRE_INSTALLER.fetchFrom(params)) {
+            //prepare desktop shortcut
+            Writer w = new BufferedWriter(new FileWriter(
+                    getConfig_DesktopShortcutFile(rootDir, params)));
+            String content = preprocessTextResource(
+                    LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                            + getConfig_DesktopShortcutFile(rootDir,
+                                    params).getName(),
+                    I18N.getString("resource.menu-shortcut-descriptor"),
+                    DEFAULT_DESKTOP_FILE_TEMPLATE, data,
+                    VERBOSE.fetchFrom(params),
+                    DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+            w.write(content);
+            w.close();
+        }
+
+        //prepare spec file
+        Writer w = new BufferedWriter(
+                new FileWriter(getConfig_SpecFile(params)));
+        String content = preprocessTextResource(
+                LinuxAppBundler.LINUX_BUNDLER_PREFIX
+                        + getConfig_SpecFile(params).getName(),
+                I18N.getString("resource.rpm-spec-file"),
+                DEFAULT_SPEC_TEMPLATE, data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        w.write(content);
+        w.close();
+
+        return true;
+    }
+
+    private Map<String, String> createReplacementData(
+            Map<String, ? super Object> params) {
+        Map<String, String> data = new HashMap<>();
+
+        data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
+        data.put("APPLICATION_FS_NAME", APP_FS_NAME.fetchFrom(params));
+        data.put("APPLICATION_PACKAGE", BUNDLE_NAME.fetchFrom(params));
+        data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
+        data.put("APPLICATION_VERSION", VERSION.fetchFrom(params));
+        data.put("APPLICATION_LAUNCHER_FILENAME",
+                APP_FS_NAME.fetchFrom(params));
+        data.put("INSTALLATION_DIRECTORY", LINUX_INSTALL_DIR.fetchFrom(params));
+        data.put("XDG_PREFIX", XDG_FILE_PREFIX.fetchFrom(params));
+        data.put("DEPLOY_BUNDLE_CATEGORY", CATEGORY.fetchFrom(params)); //TODO rpm categories
+        data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
+        data.put("APPLICATION_SUMMARY", TITLE.fetchFrom(params));
+        data.put("APPLICATION_LICENSE_TYPE", LICENSE_TYPE.fetchFrom(params));
+        data.put("APPLICATION_LICENSE_FILE", getLicenseFileString(params));
+        String deps = LINUX_PACKAGE_DEPENDENCIES.fetchFrom(params);
+        data.put("PACKAGE_DEPENDENCIES",
+                deps.isEmpty() ? "" : "Requires: " + deps);
+        data.put("CREATE_JRE_INSTALLER",
+                Arguments.CREATE_JRE_INSTALLER.fetchFrom(params).toString());
+        return data;
+    }
+
+    private File getConfig_DesktopShortcutFile(File rootDir,
+            Map<String, ? super Object> params) {
+        return new File(rootDir,
+                APP_FS_NAME.fetchFrom(params) + ".desktop");
+    }
+
+    private File getConfig_IconFile(File rootDir,
+            Map<String, ? super Object> params) {
+        return new File(rootDir,
+                APP_FS_NAME.fetchFrom(params) + ".png");
+    }
+
+    private File getConfig_SpecFile(Map<String, ? super Object> params) {
+        return new File(RPM_IMAGE_DIR.fetchFrom(params),
+                APP_FS_NAME.fetchFrom(params) + ".spec");
+    }
+
+    private File buildRPM(Map<String, ? super Object> params,
+            File outdir) throws IOException {
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.outputting-bundle-location"),
+                outdir.getAbsolutePath()));
+
+        File broot = new File(BUILD_ROOT.fetchFrom(params), "rmpbuildroot");
+
+        outdir.mkdirs();
+
+        //run rpmbuild
+        ProcessBuilder pb = new ProcessBuilder(
+                TOOL_RPMBUILD,
+                "-bb", getConfig_SpecFile(params).getAbsolutePath(),
+//                "--define", "%__jar_repack %{nil}",
+//debug: improves build time (but will require unpack to install?)
+                "--define", "%_sourcedir "
+                        + RPM_IMAGE_DIR.fetchFrom(params).getAbsolutePath(),
+                //save result to output dir
+                "--define", "%_rpmdir " + outdir.getAbsolutePath(),
+                //do not use other system directories to build as current user
+                "--define", "%_topdir " + broot.getAbsolutePath()
+        );
+        pb = pb.directory(RPM_IMAGE_DIR.fetchFrom(params));
+        IOUtils.exec(pb, ECHO_MODE.fetchFrom(params));
+
+        if (!Log.isDebug()) {
+            IOUtils.deleteRecursive(broot);
+        }
+
+        Log.info(MessageFormat.format(
+                I18N.getString("message.output-bundle-location"),
+                outdir.getAbsolutePath()));
+
+        // presume the result is the ".rpm" file with the newest modified time
+        // not the best solution, but it is the most reliable
+        File result = null;
+        long lastModified = 0;
+        File[] list = outdir.listFiles();
+        if (list != null) {
+            for (File f : list) {
+                if (f.getName().endsWith(".rpm") &&
+                        f.lastModified() > lastModified) {
+                    result = f;
+                    lastModified = f.lastModified();
+                }
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public String getName() {
+        return I18N.getString("bundler.name");
+    }
+
+    @Override
+    public String getDescription() {
+        return I18N.getString("bundler.description");
+    }
+
+    @Override
+    public String getID() {
+        return "rpm";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "INSTALLER";
+    }
+
+    @Override
+    public Collection<BundlerParamInfo<?>> getBundleParameters() {
+        Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
+        results.addAll(LinuxAppBundler.getAppBundleParameters());
+        results.addAll(getRpmBundleParameters());
+        return results;
+    }
+
+    public static Collection<BundlerParamInfo<?>> getRpmBundleParameters() {
+        return Arrays.asList(
+                BUNDLE_NAME,
+                CATEGORY,
+                DESCRIPTION,
+                LinuxAppBundler.ICON_PNG,
+                LICENSE_FILE,
+                LICENSE_TYPE,
+                TITLE,
+                VENDOR
+        );
+    }
+
+    @Override
+    public File execute(
+            Map<String, ? super Object> params, File outputParentDir) {
+        return bundle(params, outputParentDir);
+    }
+
+    @Override
+    public boolean supported() {
+        return (Platform.getPlatform() == Platform.LINUX);
+    }
+
+    public int getSquareSizeOfImage(File f) {
+        try {
+            BufferedImage bi = ImageIO.read(f);
+            if (bi.getWidth() == bi.getHeight()) {
+                return bi.getWidth();
+            } else {
+                return 0;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/builders/linux/LinuxAppImageBuilder.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,4 @@
+param.icon-png.name=.png Icon
+param.icon-png.description=Icon for the application, in PNG format.
+
+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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/builders/linux/LinuxAppImageBuilder_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,4 @@
+param.icon-png.name=.png\u30A2\u30A4\u30B3\u30F3
+param.icon-png.description=PNG\u5F62\u5F0F\u3067\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30A2\u30A4\u30B3\u30F3\u3002
+
+message.icon-not-png=\u6307\u5B9A\u3057\u305F\u30A2\u30A4\u30B3\u30F3"{0}"\u306FPNG\u30D5\u30A1\u30A4\u30EB\u3067\u306F\u306A\u304F\u3001\u4F7F\u7528\u3055\u308C\u307E\u305B\u3093\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3\u304C\u305D\u306E\u4F4D\u7F6E\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/builders/linux/LinuxAppImageBuilder_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,4 @@
+param.icon-png.name=.png \u56FE\u6807
+param.icon-png.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u56FE\u6807, \u91C7\u7528 PNG \u683C\u5F0F\u3002
+
+message.icon-not-png=\u6307\u5B9A\u7684\u56FE\u6807 "{0}" \u4E0D\u662F PNG \u6587\u4EF6, \u4E0D\u4F1A\u4F7F\u7528\u3002\u5C06\u4F7F\u7528\u9ED8\u8BA4\u56FE\u6807\u4EE3\u66FF\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/LinuxAppBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,28 @@
+bundler.name=Linux Application Image
+bundler.description=A Directory based image of a linux Application with an optionally co-bundled JRE.  Used as a base for the Installer bundlers.
+
+param.raw-executable-url.name=Launcher URL
+param.raw-executable-url.description=Override the packager default launcher with a custom launcher.
+
+param.icon-png.name=.png Icon
+param.icon-png.description=Icon for the application, in PNG format.
+
+param.runtime.name=JRE
+param.runtime.description=The Java Runtime to co-bundle.  The default value is the current JRE running the bundler.  A value of null will cause no JRE to be co-bundled and the system JRE will be used to launch the application.
+
+param.linux-install-dir.name=Linux Installation Directory
+param.linux-install-dir.description=Installation directory of the application on Linux.
+
+param.linux-package-dependencies.name=Linux Package Dependencies
+param.linux-package-dependencies.description=Required packages or capabilities for the application.
+
+error.parameters-null=Parameters map is null.
+error.parameters-null.advice=Pass in a non-null parameters map.
+error.no-linux-resources=Java Packager does not support Linux.
+error.no-linux-resources.advice=Please use the Java Packager that ships with Oracle JDK for Linux.
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+
+message.creating-bundle-location=Creating app bundle\: {0}
+message.jvm-user-arg-is-null=WARNING\: a jvmuserarg has a null name or value
+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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/LinuxAppBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,22 @@
+bundler.name=Linux\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8
+bundler.description=\u30AA\u30D7\u30B7\u30E7\u30F3\u3067JRE\u304C\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u3066\u3044\u308BLinux\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FB\u30D9\u30FC\u30B9\u306E\u30A4\u30E1\u30FC\u30B8\u3002\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FB\u30D0\u30F3\u30C9\u30E9\u306E\u30D9\u30FC\u30B9\u3068\u3057\u3066\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+
+param.raw-executable-url.name=\u30E9\u30F3\u30C1\u30E3URL
+param.raw-executable-url.description=\u30D1\u30C3\u30B1\u30FC\u30B8\u30E3\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30E9\u30F3\u30C1\u30E3\u3092\u30AB\u30B9\u30BF\u30E0\u30FB\u30E9\u30F3\u30C1\u30E3\u3067\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u3059\u3002
+
+param.icon-png.name=.png\u30A2\u30A4\u30B3\u30F3
+param.icon-png.description=PNG\u5F62\u5F0F\u3067\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30A2\u30A4\u30B3\u30F3\u3002
+
+param.runtime.name=JRE
+param.runtime.description=\u30D0\u30F3\u30C9\u30EB\u3059\u308BJava\u30E9\u30F3\u30BF\u30A4\u30E0\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u306F\u3001\u30D0\u30F3\u30C9\u30E9\u3092\u5B9F\u884C\u3057\u3066\u3044\u308B\u73FE\u5728\u306EJRE\u3067\u3059\u3002\u5024\u304Cnull\u306E\u5834\u5408\u3001JRE\u306F\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305A\u3001\u30B7\u30B9\u30C6\u30E0\u306EJRE\u304C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u8D77\u52D5\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+
+error.parameters-null=\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u304Cnull\u3067\u3059\u3002
+error.parameters-null.advice=\u975Enull\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u3067\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.no-linux-resources=Java\u30D1\u30C3\u30B1\u30FC\u30B8\u30E3\u306FLinux\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3066\u3044\u307E\u305B\u3093\u3002
+error.no-linux-resources.advice=Oracle JDK for Linux\u306B\u4ED8\u5C5E\u3057\u3066\u3044\u308BJava\u30D1\u30C3\u30B1\u30FC\u30B8\u30E3\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+
+message.creating-bundle-location=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059: {0}
+message.jvm-user-arg-is-null=\u8B66\u544A: jvmuserarg\u306Bnull\u306E\u540D\u524D\u307E\u305F\u306F\u5024\u304C\u3042\u308A\u307E\u3059
+message.icon-not-png=\u6307\u5B9A\u3057\u305F\u30A2\u30A4\u30B3\u30F3"{0}"\u306FPNG\u30D5\u30A1\u30A4\u30EB\u3067\u306F\u306A\u304F\u3001\u4F7F\u7528\u3055\u308C\u307E\u305B\u3093\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3\u304C\u305D\u306E\u4F4D\u7F6E\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/LinuxAppBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,22 @@
+bundler.name=Linux \u5E94\u7528\u7A0B\u5E8F\u6620\u50CF
+bundler.description=\u4E00\u4E2A\u57FA\u4E8E\u76EE\u5F55\u7684 linux \u5E94\u7528\u7A0B\u5E8F\u6620\u50CF, \u53EF\u4EE5\u9009\u62E9\u6027\u5730\u5E26\u6709\u5171\u540C\u6253\u5305\u7684 JRE\u3002\u7528\u4F5C\u5B89\u88C5\u7A0B\u5E8F\u6253\u5305\u7A0B\u5E8F\u7684\u57FA\u7840\u3002
+
+param.raw-executable-url.name=\u542F\u52A8\u7A0B\u5E8F URL
+param.raw-executable-url.description=\u4F7F\u7528\u5B9A\u5236\u542F\u52A8\u7A0B\u5E8F\u8986\u76D6\u6253\u5305\u7A0B\u5E8F\u9ED8\u8BA4\u542F\u52A8\u7A0B\u5E8F\u3002
+
+param.icon-png.name=.png \u56FE\u6807
+param.icon-png.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u56FE\u6807, \u91C7\u7528 PNG \u683C\u5F0F\u3002
+
+param.runtime.name=JRE
+param.runtime.description=\u8981\u5171\u540C\u6253\u5305\u7684 Java \u8FD0\u884C\u65F6\u3002\u9ED8\u8BA4\u503C\u4E3A\u8FD0\u884C\u6253\u5305\u7A0B\u5E8F\u7684\u5F53\u524D JRE\u3002\u503C\u4E3A\u7A7A\u503C\u5C06\u5BFC\u81F4\u4E0D\u4F1A\u5171\u540C\u6253\u5305\u4EFB\u4F55 JRE, \u5E76\u4E14\u5C06\u4F7F\u7528\u7CFB\u7EDF JRE \u6765\u542F\u52A8\u5E94\u7528\u7A0B\u5E8F\u3002
+
+error.parameters-null=\u53C2\u6570\u6620\u5C04\u4E3A\u7A7A\u503C\u3002
+error.parameters-null.advice=\u8BF7\u4F20\u5165\u975E\u7A7A\u53C2\u6570\u6620\u5C04\u3002
+error.no-linux-resources=Java \u6253\u5305\u7A0B\u5E8F\u4E0D\u652F\u6301 Linux\u3002
+error.no-linux-resources.advice=\u8BF7\u4F7F\u7528 Oracle JDK for Linux \u4E2D\u9644\u5E26\u7684 Java \u6253\u5305\u7A0B\u5E8F\u3002
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+
+message.creating-bundle-location=\u6B63\u5728\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u5305: {0}
+message.jvm-user-arg-is-null=\u8B66\u544A: jvmuserarg \u7684\u540D\u79F0\u6216\u503C\u4E3A\u7A7A\u503C
+message.icon-not-png=\u6307\u5B9A\u7684\u56FE\u6807 "{0}" \u4E0D\u662F PNG \u6587\u4EF6, \u4E0D\u4F1A\u4F7F\u7528\u3002\u5C06\u4F7F\u7528\u9ED8\u8BA4\u56FE\u6807\u4EE3\u66FF\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/LinuxDebBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,83 @@
+bundler.name=DEB Installer
+bundler.description=Linux Debian Bundle.
+
+param.app-bundler.name=
+param.app-bundler.description=
+
+param.bundle-name.name=
+param.bundle-name.description=
+
+param.full-package-name.name=
+param.full-package-name.description=
+
+param.image-dir.name=
+param.image-dir.description=
+
+param.config-root.name=
+param.config-root.description=
+
+param.app-image-root.name=
+param.app-image-root.description=
+
+param.config-dir.name=
+param.config-dir.description=
+
+param.maintainer-email.name=
+param.maintainer-email.description=
+
+param.maintainer-name.name=
+param.maintainer-name.description=
+
+param.license-type.name=
+param.license-type.description=
+
+param.license-text.name=
+param.license-text.description=
+
+param.xdg-prefix.name=Prefix for XDG files (mime, desktop)
+param.xdg-prefix.description=Prefix for XDG MimeInfo and Desktop Files.  Defaults to <vendor>-<appName>, with spaces dropped.
+
+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.deb-copyright-file=DEB copyright file
+resource.deb-init-script=DEB init script
+resource.menu-shortcut-descriptor=Menu shortcut descriptor
+resource.menu-icon=menu icon
+
+error.parameters-null=Parameters map is null.
+error.parameters-null.advice=Pass in a non-null parameters map.
+
+error.tool-not-found=Can not find {0}.
+error.tool-not-found.advice=Please install required packages.
+
+error.license-missing=Specified license file is missing.
+error.license-missing.advice=Make sure that "{0}" references a file in the app resources, and that it is relative to the basedir "{1}".
+
+error.launcher-name-too-long=The bundle name "{0}" is too long for a daemon.
+error.launcher-name-too-long.advice=Set a bundler argument "{0}" to a bundle name that is shorter than 16 characters.
+
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+
+error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}.
+error.no-content-types-for-file-association.advice=For Linux Bundling specify one and only one MIME type for each file association.
+
+error.too-many-content-types-for-file-association=More than one MIME types was specified for File Association number {0}.
+error.too-many-content-types-for-file-association.advice=For Linux Bundling specify one and only one MIME type for each file association.
+
+error.no-support-for-peruser-daemons=Bundler doesn't support per-user daemons.
+error.no-support-for-peruser-daemons.advice=Make sure that the system wide hint is set to true.
+
+error.invalid-value-for-package-name=Invalid value "{0}" for the package name.
+error.invalid-value-for-package-name.advice=Set the "linux.bundleName" parameter 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.test-for-tool=Test for [{0}]. Result\: {1}
+message.debug-working-directory=Kept working directory for debug\: {0}
+message.config-save-location=Config files are saved to {0}. Use them to customize package.
+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.creating-association-with-null-extension=Creating association with null extension.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/LinuxDebBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,83 @@
+bundler.name=DEB\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9
+bundler.description=Linux Debian\u30D0\u30F3\u30C9\u30EB\u3002
+
+param.app-bundler.name=
+param.app-bundler.description=
+
+param.bundle-name.name=
+param.bundle-name.description=
+
+param.full-package-name.name=
+param.full-package-name.description=
+
+param.image-dir.name=
+param.image-dir.description=
+
+param.config-root.name=
+param.config-root.description=
+
+param.app-image-root.name=
+param.app-image-root.description=
+
+param.config-dir.name=
+param.config-dir.description=
+
+param.maintainer-email.name=
+param.maintainer-email.description=
+
+param.maintainer-name.name=
+param.maintainer-name.description=
+
+param.license-type.name=
+param.license-type.description=
+
+param.license-text.name=
+param.license-text.description=
+
+param.xdg-prefix.name=XDG\u30D5\u30A1\u30A4\u30EB\u306E\u63A5\u982D\u8F9E(mime\u3001\u30C7\u30B9\u30AF\u30C8\u30C3\u30D7)
+param.xdg-prefix.description=XDG MimeInfo\u304A\u3088\u3073\u30C7\u30B9\u30AF\u30C8\u30C3\u30D7\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u63A5\u982D\u8F9E\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F<vendor>-<appName>\u3067\u3042\u308A\u3001\u30B9\u30DA\u30FC\u30B9\u306F\u524A\u9664\u3055\u308C\u307E\u3059\u3002
+
+resource.deb-control-file=DEB\u5236\u5FA1\u30D5\u30A1\u30A4\u30EB
+resource.deb-preinstall-script=DEB\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u524D\u30B9\u30AF\u30EA\u30D7\u30C8
+resource.deb-prerm-script=DEB prerm\u30B9\u30AF\u30EA\u30D7\u30C8
+resource.deb-postinstall-script=DEB\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u5F8C\u30B9\u30AF\u30EA\u30D7\u30C8
+resource.deb-postrm-script=DEB postrm\u30B9\u30AF\u30EA\u30D7\u30C8
+resource.deb-copyright-file=DEB\u30B3\u30D4\u30FC\u30E9\u30A4\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB
+resource.deb-init-script=DEB\u521D\u671F\u5316\u30B9\u30AF\u30EA\u30D7\u30C8
+resource.menu-shortcut-descriptor=\u30E1\u30CB\u30E5\u30FC\u30FB\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF
+resource.menu-icon=\u30E1\u30CB\u30E5\u30FC\u30FB\u30A2\u30A4\u30B3\u30F3
+
+error.parameters-null=\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u304Cnull\u3067\u3059\u3002
+error.parameters-null.advice=\u975Enull\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u3067\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.tool-not-found={0}\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002
+error.tool-not-found.advice=\u5FC5\u8981\u306A\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.license-missing=\u6307\u5B9A\u3057\u305F\u30E9\u30A4\u30BB\u30F3\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\u3002
+error.license-missing.advice="{0}"\u304C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30EA\u30BD\u30FC\u30B9\u5185\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u53C2\u7167\u3057\u3001\u30D9\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA"{1}"\u306B\u5BFE\u3057\u3066\u76F8\u5BFE\u7684\u3067\u3042\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.launcher-name-too-long=\u30D0\u30F3\u30C9\u30EB\u540D"{0}"\u304C\u3001\u30C7\u30FC\u30E2\u30F3\u306B\u5BFE\u3057\u3066\u9577\u3059\u304E\u307E\u3059\u3002
+error.launcher-name-too-long.advice=\u30D0\u30F3\u30C9\u30E9\u5F15\u6570"{0}"\u309216\u6587\u5B57\u672A\u6E80\u306E\u30D0\u30F3\u30C9\u30EB\u540D\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+
+error.no-content-types-for-file-association=\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u756A\u53F7{0}\u306BMIME\u30BF\u30A4\u30D7\u304C\u6307\u5B9A\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002
+error.no-content-types-for-file-association.advice=Linux\u30D0\u30F3\u30C9\u30EB\u306E\u5834\u5408\u3001\u5404\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u306BMIME\u30BF\u30A4\u30D7\u30921\u3064\u3060\u3051\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.too-many-content-types-for-file-association=\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u756A\u53F7{0}\u306B\u8907\u6570\u306EMIME\u30BF\u30A4\u30D7\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F\u3002
+error.too-many-content-types-for-file-association.advice=Linux\u30D0\u30F3\u30C9\u30EB\u306E\u5834\u5408\u3001\u5404\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u306BMIME\u30BF\u30A4\u30D7\u30921\u3064\u3060\u3051\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.no-support-for-peruser-daemons=\u30D0\u30F3\u30C9\u30E9\u306F\u3001\u30E6\u30FC\u30B6\u30FC\u5358\u4F4D\u306E\u30C7\u30FC\u30E2\u30F3\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3066\u3044\u307E\u305B\u3093\u3002
+error.no-support-for-peruser-daemons.advice=\u30B7\u30B9\u30C6\u30E0\u5168\u4F53\u306E\u30D2\u30F3\u30C8\u304Ctrue\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.invalid-value-for-package-name=\u30D1\u30C3\u30B1\u30FC\u30B8\u540D\u306B\u5BFE\u3057\u3066\u5024"{0}"\u306F\u7121\u52B9\u3067\u3059\u3002
+error.invalid-value-for-package-name.advice="linux.bundleName"\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u6709\u52B9\u306ADebian\u30D1\u30C3\u30B1\u30FC\u30B8\u540D\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u540D\u306B\u306F\u3001\u5C0F\u6587\u5B57(a-z)\u3001\u6570\u5B57(0-9)\u3001\u30D7\u30E9\u30B9(+)\u3068\u30DE\u30A4\u30CA\u30B9(-)\u306E\u8A18\u53F7\u304A\u3088\u3073\u30D4\u30EA\u30AA\u30C9(.)\u306E\u307F\u3092\u542B\u3081\u308B\u3088\u3046\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u9577\u3055\u306F2\u6587\u5B57\u4EE5\u4E0A\u3068\u3057\u3001\u82F1\u6570\u5B57\u3067\u59CB\u3081\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
+
+message.test-for-tool=[{0}]\u306E\u30C6\u30B9\u30C8\u3002\u7D50\u679C: {1}
+message.debug-working-directory=\u30C7\u30D0\u30C3\u30B0\u306E\u4F5C\u696D\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u4FDD\u6301\u3055\u308C\u307E\u3057\u305F: {0}
+message.config-save-location=\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C{0}\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B\u306B\u306F\u3053\u308C\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+message.outputting-to-location=\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u306EDEB\u3092\u6B21\u306B\u751F\u6210\u3057\u3066\u3044\u307E\u3059: {0}
+message.output-to-location=\u30D1\u30C3\u30B1\u30FC\u30B8(.deb)\u306F\u6B21\u306B\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F: {0}
+message.debs-like-licenses=Debian\u30D1\u30C3\u30B1\u30FC\u30B8\u3067\u306F\u30E9\u30A4\u30BB\u30F3\u30B9\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\u30E9\u30A4\u30BB\u30F3\u30B9\u304C\u306A\u3044\u5834\u5408\u3001\u4E00\u90E8\u306ELinux\u30C7\u30A3\u30B9\u30C8\u30EA\u30D3\u30E5\u30FC\u30B7\u30E7\u30F3\u3067\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u54C1\u8CEA\u306B\u554F\u984C\u304C\u767A\u751F\u3059\u308B\u5834\u5408\u304C\u3042\u308A\u307E\u3059\u3002
+message.creating-association-with-null-extension=null\u62E1\u5F35\u5B50\u3068\u306E\u95A2\u9023\u4ED8\u3051\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/LinuxDebBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,83 @@
+bundler.name=DEB \u5B89\u88C5\u7A0B\u5E8F
+bundler.description=Linux Debian \u5305\u3002
+
+param.app-bundler.name=
+param.app-bundler.description=
+
+param.bundle-name.name=
+param.bundle-name.description=
+
+param.full-package-name.name=
+param.full-package-name.description=
+
+param.image-dir.name=
+param.image-dir.description=
+
+param.config-root.name=
+param.config-root.description=
+
+param.app-image-root.name=
+param.app-image-root.description=
+
+param.config-dir.name=
+param.config-dir.description=
+
+param.maintainer-email.name=
+param.maintainer-email.description=
+
+param.maintainer-name.name=
+param.maintainer-name.description=
+
+param.license-type.name=
+param.license-type.description=
+
+param.license-text.name=
+param.license-text.description=
+
+param.xdg-prefix.name=XDG \u6587\u4EF6 (mime, desktop) \u7684\u524D\u7F00
+param.xdg-prefix.description=XDG MimeInfo \u548C Desktop \u6587\u4EF6\u7684\u524D\u7F00\u3002\u9ED8\u8BA4\u4E3A <vendor>-<appName>, \u4E0D\u542B\u7A7A\u683C\u3002
+
+resource.deb-control-file=DEB \u63A7\u5236\u6587\u4EF6
+resource.deb-preinstall-script=DEB \u5B89\u88C5\u524D\u811A\u672C
+resource.deb-prerm-script=DEB \u5220\u9664\u524D\u811A\u672C
+resource.deb-postinstall-script=DEB \u5B89\u88C5\u540E\u811A\u672C
+resource.deb-postrm-script=DEB \u5220\u9664\u540E\u811A\u672C
+resource.deb-copyright-file=DEB \u7248\u6743\u6587\u4EF6
+resource.deb-init-script=DEB \u521D\u59CB\u5316\u811A\u672C
+resource.menu-shortcut-descriptor=\u83DC\u5355\u5FEB\u6377\u65B9\u5F0F\u63CF\u8FF0\u7B26
+resource.menu-icon=\u83DC\u5355\u56FE\u6807
+
+error.parameters-null=\u53C2\u6570\u6620\u5C04\u4E3A\u7A7A\u503C\u3002
+error.parameters-null.advice=\u8BF7\u4F20\u5165\u975E\u7A7A\u53C2\u6570\u6620\u5C04\u3002
+
+error.tool-not-found=\u627E\u4E0D\u5230{0}\u3002
+error.tool-not-found.advice=\u8BF7\u5B89\u88C5\u6240\u9700\u7684\u7A0B\u5E8F\u5305\u3002
+
+error.license-missing=\u7F3A\u5C11\u6307\u5B9A\u7684\u8BB8\u53EF\u8BC1\u6587\u4EF6\u3002
+error.license-missing.advice=\u8BF7\u786E\u4FDD "{0}" \u5F15\u7528\u5E94\u7528\u7A0B\u5E8F\u8D44\u6E90\u4E2D\u7684\u6587\u4EF6, \u5E76\u4E14\u4F7F\u7528\u57FA\u76EE\u5F55 "{1}" \u7684\u76F8\u5BF9\u76EE\u5F55\u3002
+
+error.launcher-name-too-long=\u5B88\u62A4\u7A0B\u5E8F\u7684\u5305\u540D "{0}" \u592A\u957F\u3002
+error.launcher-name-too-long.advice=\u5C06\u6253\u5305\u7A0B\u5E8F\u53C2\u6570 "{0}" \u8BBE\u7F6E\u4E3A\u5C11\u4E8E 16 \u4E2A\u5B57\u7B26\u7684\u5305\u540D\u3002
+
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+
+error.no-content-types-for-file-association=\u6CA1\u6709\u4E3A\u6587\u4EF6\u5173\u8054\u53F7{0}\u6307\u5B9A MIME \u7C7B\u578B\u3002
+error.no-content-types-for-file-association.advice=\u5BF9\u4E8E Linux \u6253\u5305, \u8BF7\u4E3A\u6BCF\u4E2A\u6587\u4EF6\u5173\u8054\u6307\u5B9A\u4E00\u4E2A\u4E14\u4EC5\u6307\u5B9A\u4E00\u4E2A MIME \u7C7B\u578B\u3002
+
+error.too-many-content-types-for-file-association=\u4E3A\u6587\u4EF6\u5173\u8054\u53F7{0}\u6307\u5B9A\u4E86\u591A\u4E2A MIME \u7C7B\u578B\u3002
+error.too-many-content-types-for-file-association.advice=\u5BF9\u4E8E Linux \u6253\u5305, \u8BF7\u4E3A\u6BCF\u4E2A\u6587\u4EF6\u5173\u8054\u6307\u5B9A\u4E00\u4E2A\u4E14\u4EC5\u6307\u5B9A\u4E00\u4E2A MIME \u7C7B\u578B\u3002
+
+error.no-support-for-peruser-daemons=\u6253\u5305\u7A0B\u5E8F\u4E0D\u652F\u6301\u6BCF\u7528\u6237\u5B88\u62A4\u7A0B\u5E8F\u3002
+error.no-support-for-peruser-daemons.advice=\u786E\u4FDD\u7CFB\u7EDF\u8303\u56F4\u63D0\u793A\u8BBE\u7F6E\u4E3A\u201C\u771F\u201D\u3002
+
+error.invalid-value-for-package-name=\u7A0B\u5E8F\u5305\u540D\u79F0\u7684\u503C "{0}" \u65E0\u6548\u3002
+error.invalid-value-for-package-name.advice=\u5C06 "linux.bundleName" \u53C2\u6570\u8BBE\u7F6E\u4E3A\u6709\u6548\u7684 Debian \u7A0B\u5E8F\u5305\u540D\u79F0\u3002\u8BF7\u6CE8\u610F, \u7A0B\u5E8F\u5305\u540D\u79F0\u53EA\u80FD\u5305\u542B\u5C0F\u5199\u5B57\u6BCD (a-z), \u6570\u5B57 (0-9), \u52A0\u53F7 (+) \u548C\u51CF\u53F7 (-) \u4EE5\u53CA\u53E5\u70B9 (.)\u3002\u540D\u79F0\u957F\u5EA6\u5FC5\u987B\u81F3\u5C11\u4E3A\u4E24\u4E2A\u5B57\u7B26\u5E76\u4E14\u5FC5\u987B\u4EE5\u5B57\u6BCD\u6570\u5B57\u5B57\u7B26\u5F00\u5934\u3002
+
+message.test-for-tool=[{0}] \u7684\u6D4B\u8BD5\u3002\u7ED3\u679C: {1}
+message.debug-working-directory=\u7528\u4E8E\u8C03\u8BD5\u7684\u5DF2\u4FDD\u7559\u5DE5\u4F5C\u76EE\u5F55: {0}
+message.config-save-location=\u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58\u5230{0}\u3002\u4F7F\u7528\u8FD9\u4E9B\u914D\u7F6E\u6587\u4EF6\u53EF\u5B9A\u5236\u7A0B\u5E8F\u5305\u3002
+message.outputting-to-location=\u6B63\u5728\u4E3A\u5B89\u88C5\u7A0B\u5E8F\u751F\u6210 DEB, \u4F4D\u7F6E: {0}
+message.output-to-location=\u7A0B\u5E8F\u5305 (.deb) \u5DF2\u4FDD\u5B58\u5230: {0}
+message.debs-like-licenses=Debian \u7A0B\u5E8F\u5305\u5E94\u6307\u5B9A\u8BB8\u53EF\u8BC1\u3002\u7F3A\u5C11\u8BB8\u53EF\u8BC1\u5C06\u5BFC\u81F4\u67D0\u4E9B Linux \u5206\u53D1\u6295\u8BC9\u5E94\u7528\u7A0B\u5E8F\u8D28\u91CF\u3002
+message.creating-association-with-null-extension=\u6B63\u5728\u4F7F\u7528\u7A7A\u6269\u5C55\u540D\u521B\u5EFA\u5173\u8054\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/LinuxResources.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011, 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.packager.internal.resources.linux;
+
+public class LinuxResources {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/LinuxRpmBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,58 @@
+bundler.name=RPM Bundle
+bundler.description=Redhat Package Manager (RPM) bundler.
+
+param.app-bundler.name=
+param.app-bundler.description=
+
+param.image-dir.name=
+param.image-dir.description=
+
+param.bundle-name.name=
+param.bundle-name.description=
+
+param.config-root.name=
+param.config-root.description=
+
+param.xdg-prefix.name=Prefix for XDG files (mime, desktop)
+param.xdg-prefix.description=Prefix for XDG MimeInfo and Desktop Files.  Defaults to <vendor>-<appName>, with spaces dropped.
+
+param.license-type.name=License Type
+param.license-type.description=License Type for RPM package.
+param.license-type.default=Unknown
+
+resource.rpm-spec-file=RPM spec file
+resource.rpm-init-script=RPM init script
+resource.menu-shortcut-descriptor=Menu shortcut descriptor
+resource.menu-icon=menu icon
+
+error.parameters-null=Parameters map is null.
+error.parameters-null.advice=Pass in a non-null parameters map.
+
+error.cannot-find-rpmbuild=Can not find rpmbuild {0} or newer.
+error.cannot-find-rpmbuild.advice=\  Install packages needed to build RPM, version {0} or newer.
+
+error.license-missing=Specified license file is missing.
+error.license-missing.advice=Make sure that "{0}" references a file in the app resources, and that it is relative file reference.
+
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+
+error.no-content-types-for-file-association=No MIME types were specified for File Association number {0}.
+error.no-content-types-for-file-association.advice=For Linux Bundling specify one and only one MIME type for each file association.
+
+error.too-many-content-types-for-file-association=More than one MIME types was specified for File Association number {0}.
+error.too-many-content-types-for-file-association.advice=For Linux Bundling specify one and only one MIME type for each file association.
+
+error.no-support-for-peruser-daemons=Bundler doesn't support per-user daemons.
+error.no-support-for-peruser-daemons.advice=Make sure that the system wide hint is set to true.
+
+error.invalid-value-for-package-name=Invalid value "{0}" for the package name.
+error.invalid-value-for-package-name.advice=Set the "linux.bundleName" parameter to a valid RPM package name. Note that the packages must be named using only the following ASCII characters:  abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._+
+
+message.test-for-tool=Test for [{0}]. Result\: {1}
+message.one-shortcut-required=At least one type of shortcut is required. Enabling menu shortcut.
+message.debug-working-directory=Kept working directory for debug\: {0}
+message.config-save-location=Config files are saved to {0}. Use them to customize package.
+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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/LinuxRpmBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,54 @@
+bundler.name=RPM\u30D0\u30F3\u30C9\u30EB
+bundler.description=RedHat Package Manager (RPM)\u306E\u30D0\u30F3\u30C9\u30E9\u3002
+
+param.app-bundler.name=
+param.app-bundler.description=
+
+param.image-dir.name=
+param.image-dir.description=
+
+param.bundle-name.name=
+param.bundle-name.description=
+
+param.config-root.name=
+param.config-root.description=
+
+param.xdg-prefix.name=XDG\u30D5\u30A1\u30A4\u30EB\u306E\u63A5\u982D\u8F9E(mime\u3001\u30C7\u30B9\u30AF\u30C8\u30C3\u30D7)
+param.xdg-prefix.description=XDG MimeInfo\u304A\u3088\u3073\u30C7\u30B9\u30AF\u30C8\u30C3\u30D7\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u63A5\u982D\u8F9E\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F<vendor>-<appName>\u3067\u3042\u308A\u3001\u30B9\u30DA\u30FC\u30B9\u306F\u524A\u9664\u3055\u308C\u307E\u3059\u3002
+
+resource.rpm-spec-file=RPM\u4ED5\u69D8\u30D5\u30A1\u30A4\u30EB
+resource.rpm-init-script=RPM\u521D\u671F\u5316\u30B9\u30AF\u30EA\u30D7\u30C8
+resource.menu-shortcut-descriptor=\u30E1\u30CB\u30E5\u30FC\u30FB\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF
+resource.menu-icon=\u30E1\u30CB\u30E5\u30FC\u30FB\u30A2\u30A4\u30B3\u30F3
+
+error.parameters-null=\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u304Cnull\u3067\u3059\u3002
+error.parameters-null.advice=\u975Enull\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u3067\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.cannot-find-rpmbuild=rpmbuild {0}\u307E\u305F\u306F\u305D\u308C\u4EE5\u964D\u306E\u3082\u306E\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002
+error.cannot-find-rpmbuild.advice=\  \u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u306F\u30D0\u30FC\u30B8\u30E7\u30F3{0}\u4EE5\u964D\u306ERPM\u3092\u30D3\u30EB\u30C9\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
+
+error.license-missing=\u6307\u5B9A\u3057\u305F\u30E9\u30A4\u30BB\u30F3\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\u3002
+error.license-missing.advice="{0}"\u304C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30EA\u30BD\u30FC\u30B9\u5185\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u53C2\u7167\u3057\u3001\u76F8\u5BFE\u30D5\u30A1\u30A4\u30EB\u53C2\u7167\u3067\u3042\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+
+error.no-content-types-for-file-association=\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u756A\u53F7{0}\u306BMIME\u30BF\u30A4\u30D7\u304C\u6307\u5B9A\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002
+error.no-content-types-for-file-association.advice=Linux\u30D0\u30F3\u30C9\u30EB\u306E\u5834\u5408\u3001\u5404\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u306BMIME\u30BF\u30A4\u30D7\u30921\u3064\u3060\u3051\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.too-many-content-types-for-file-association=\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u756A\u53F7{0}\u306B\u8907\u6570\u306EMIME\u30BF\u30A4\u30D7\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F\u3002
+error.too-many-content-types-for-file-association.advice=Linux\u30D0\u30F3\u30C9\u30EB\u306E\u5834\u5408\u3001\u5404\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u306BMIME\u30BF\u30A4\u30D7\u30921\u3064\u3060\u3051\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.no-support-for-peruser-daemons=\u30D0\u30F3\u30C9\u30E9\u306F\u3001\u30E6\u30FC\u30B6\u30FC\u5358\u4F4D\u306E\u30C7\u30FC\u30E2\u30F3\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3066\u3044\u307E\u305B\u3093\u3002
+error.no-support-for-peruser-daemons.advice=\u30B7\u30B9\u30C6\u30E0\u5168\u4F53\u306E\u30D2\u30F3\u30C8\u304Ctrue\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.invalid-value-for-package-name=\u30D1\u30C3\u30B1\u30FC\u30B8\u540D\u306B\u5BFE\u3057\u3066\u5024"{0}"\u306F\u7121\u52B9\u3067\u3059\u3002
+error.invalid-value-for-package-name.advice="linux.bundleName"\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u6709\u52B9\u306ARPM\u30D1\u30C3\u30B1\u30FC\u30B8\u540D\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u540D\u306F\u3001\u6B21\u306EASCII\u6587\u5B57\u306E\u307F\u3092\u4F7F\u7528\u3057\u3066\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._+
+
+message.test-for-tool=[{0}]\u306E\u30C6\u30B9\u30C8\u3002\u7D50\u679C: {1}
+message.one-shortcut-required=\u5C11\u306A\u304F\u3068\u30821\u3064\u306E\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u30FB\u30BF\u30A4\u30D7\u304C\u5FC5\u8981\u3067\u3059\u3002\u30E1\u30CB\u30E5\u30FC\u30FB\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u6709\u52B9\u5316\u3057\u3066\u3044\u307E\u3059\u3002
+message.debug-working-directory=\u30C7\u30D0\u30C3\u30B0\u306E\u4F5C\u696D\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u4FDD\u6301\u3055\u308C\u307E\u3057\u305F: {0}
+message.config-save-location=\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C{0}\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B\u306B\u306F\u3053\u308C\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+message.outputting-bundle-location=\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u306ERPM\u3092\u6B21\u306B\u751F\u6210\u3057\u3066\u3044\u307E\u3059: {0}
+message.output-bundle-location=\u30D1\u30C3\u30B1\u30FC\u30B8(.rpm)\u306F\u6B21\u306B\u4FDD\u5B58\u3055\u308C\u307E\u3057\u305F: {0}
+message.creating-association-with-null-extension=null\u62E1\u5F35\u5B50\u3068\u306E\u95A2\u9023\u4ED8\u3051\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/LinuxRpmBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,54 @@
+bundler.name=RPM \u5305
+bundler.description=Redhat Package Manager (RPM) \u6253\u5305\u7A0B\u5E8F\u3002
+
+param.app-bundler.name=
+param.app-bundler.description=
+
+param.image-dir.name=
+param.image-dir.description=
+
+param.bundle-name.name=
+param.bundle-name.description=
+
+param.config-root.name=
+param.config-root.description=
+
+param.xdg-prefix.name=XDG \u6587\u4EF6 (mime, desktop) \u7684\u524D\u7F00
+param.xdg-prefix.description=XDG MimeInfo \u548C Desktop \u6587\u4EF6\u7684\u524D\u7F00\u3002\u9ED8\u8BA4\u4E3A <vendor>-<appName>, \u4E0D\u542B\u7A7A\u683C\u3002
+
+resource.rpm-spec-file=RPM \u89C4\u8303\u6587\u4EF6
+resource.rpm-init-script=RPM \u521D\u59CB\u5316\u811A\u672C
+resource.menu-shortcut-descriptor=\u83DC\u5355\u5FEB\u6377\u65B9\u5F0F\u63CF\u8FF0\u7B26
+resource.menu-icon=\u83DC\u5355\u56FE\u6807
+
+error.parameters-null=\u53C2\u6570\u6620\u5C04\u4E3A\u7A7A\u503C\u3002
+error.parameters-null.advice=\u8BF7\u4F20\u5165\u975E\u7A7A\u53C2\u6570\u6620\u5C04\u3002
+
+error.cannot-find-rpmbuild=\u627E\u4E0D\u5230 rpmbuild {0} \u6216\u66F4\u65B0\u7248\u672C\u3002
+error.cannot-find-rpmbuild.advice=\  \u8BF7\u5B89\u88C5\u6784\u5EFA RPM \u7248\u672C {0} \u6216\u66F4\u65B0\u7248\u672C\u6240\u9700\u7684\u7A0B\u5E8F\u5305\u3002
+
+error.license-missing=\u7F3A\u5C11\u6307\u5B9A\u7684\u8BB8\u53EF\u8BC1\u6587\u4EF6\u3002
+error.license-missing.advice=\u786E\u4FDD "{0}" \u5F15\u7528\u5E94\u7528\u7A0B\u5E8F\u8D44\u6E90\u4E2D\u7684\u6587\u4EF6, \u5E76\u4E14\u662F\u76F8\u5BF9\u6587\u4EF6\u5F15\u7528\u3002
+
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+
+error.no-content-types-for-file-association=\u6CA1\u6709\u4E3A\u6587\u4EF6\u5173\u8054\u53F7{0}\u6307\u5B9A MIME \u7C7B\u578B\u3002
+error.no-content-types-for-file-association.advice=\u5BF9\u4E8E Linux \u6253\u5305, \u8BF7\u4E3A\u6BCF\u4E2A\u6587\u4EF6\u5173\u8054\u6307\u5B9A\u4E00\u4E2A\u4E14\u4EC5\u6307\u5B9A\u4E00\u4E2A MIME \u7C7B\u578B\u3002
+
+error.too-many-content-types-for-file-association=\u4E3A\u6587\u4EF6\u5173\u8054\u53F7{0}\u6307\u5B9A\u4E86\u591A\u4E2A MIME \u7C7B\u578B\u3002
+error.too-many-content-types-for-file-association.advice=\u5BF9\u4E8E Linux \u6253\u5305, \u8BF7\u4E3A\u6BCF\u4E2A\u6587\u4EF6\u5173\u8054\u6307\u5B9A\u4E00\u4E2A\u4E14\u4EC5\u6307\u5B9A\u4E00\u4E2A MIME \u7C7B\u578B\u3002
+
+error.no-support-for-peruser-daemons=\u6253\u5305\u7A0B\u5E8F\u4E0D\u652F\u6301\u6BCF\u7528\u6237\u5B88\u62A4\u7A0B\u5E8F\u3002
+error.no-support-for-peruser-daemons.advice=\u786E\u4FDD\u7CFB\u7EDF\u8303\u56F4\u63D0\u793A\u8BBE\u7F6E\u4E3A\u201C\u771F\u201D\u3002
+
+error.invalid-value-for-package-name=\u7A0B\u5E8F\u5305\u540D\u79F0\u7684\u503C "{0}" \u65E0\u6548\u3002
+error.invalid-value-for-package-name.advice=\u5C06 "linux.bundleName" \u53C2\u6570\u8BBE\u7F6E\u4E3A\u6709\u6548\u7684 RPM \u7A0B\u5E8F\u5305\u540D\u79F0\u3002\u8BF7\u6CE8\u610F, \u7A0B\u5E8F\u5305\u540D\u79F0\u53EA\u80FD\u4F7F\u7528\u4EE5\u4E0B ASCII \u5B57\u7B26: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._+
+
+message.test-for-tool=[{0}] \u7684\u6D4B\u8BD5\u3002\u7ED3\u679C: {1}
+message.one-shortcut-required=\u81F3\u5C11\u9700\u8981\u4E00\u79CD\u7C7B\u578B\u7684\u5FEB\u6377\u65B9\u5F0F\u3002\u6B63\u5728\u542F\u7528\u83DC\u5355\u5FEB\u6377\u65B9\u5F0F\u3002
+message.debug-working-directory=\u7528\u4E8E\u8C03\u8BD5\u7684\u5DF2\u4FDD\u7559\u5DE5\u4F5C\u76EE\u5F55: {0}
+message.config-save-location=\u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58\u5230{0}\u3002\u4F7F\u7528\u8FD9\u4E9B\u914D\u7F6E\u6587\u4EF6\u53EF\u5B9A\u5236\u7A0B\u5E8F\u5305\u3002
+message.outputting-bundle-location=\u6B63\u5728\u4E3A\u5B89\u88C5\u7A0B\u5E8F\u751F\u6210 RPM, \u4F4D\u7F6E: {0}
+message.output-bundle-location=\u7A0B\u5E8F\u5305 (.rpm) \u5DF2\u4FDD\u5B58\u5230: {0}
+message.creating-association-with-null-extension=\u6B63\u5728\u4F7F\u7528\u7A7A\u6269\u5C55\u540D\u521B\u5EFA\u5173\u8054\u3002
Binary file src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/javalogo_white_16.png has changed
Binary file src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/javalogo_white_32.png has changed
Binary file src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/javalogo_white_48.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/template.control	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,10 @@
+Package: APPLICATION_PACKAGE
+Version: APPLICATION_VERSION
+Section: unknown
+Maintainer: APPLICATION_MAINTAINER
+Priority: optional
+Architecture: APPLICATION_ARCH
+Provides: APPLICATION_PACKAGE
+Description: APPLICATION_SUMMARY
+Installed-Size: APPLICATION_INSTALLED_SIZE
+PACKAGE_DEPENDENCIES
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/template.copyright	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,8 @@
+
+Copyright:
+
+    APPLICATION_COPYRIGHT
+
+License:
+
+    APPLICATION_LICENSE_TEXT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/template.desktop	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Name=APPLICATION_NAME
+Comment=APPLICATION_SUMMARY
+Exec=INSTALLATION_DIRECTORY/APPLICATION_FS_NAME/APPLICATION_LAUNCHER_FILENAME
+Icon=INSTALLATION_DIRECTORY/APPLICATION_FS_NAME/APPLICATION_LAUNCHER_FILENAME.png
+Terminal=false
+Type=Application
+Categories=DEPLOY_BUNDLE_CATEGORY
+DESKTOP_MIMES
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/template.postinst	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,61 @@
+#!/bin/sh
+# postinst script for APPLICATION_NAME
+#
+# 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 http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+case "$1" in
+    configure)
+        if [ "CREATE_JRE_INSTALLER" != "true" ]; then
+            echo Adding shortcut to the menu
+SECONDARY_LAUNCHERS_INSTALL
+            xdg-desktop-menu install --novendor INSTALLATION_DIRECTORY/APPLICATION_FS_NAME/APPLICATION_LAUNCHER_FILENAME.desktop
+FILE_ASSOCIATION_INSTALL
+        fi
+        if [ "SERVICE_HINT" = "true" ]; then
+            echo Installing daemon
+            cp INSTALLATION_DIRECTORY/APPLICATION_FS_NAME/APPLICATION_PACKAGE.init /etc/init.d/APPLICATION_PACKAGE
+
+            if [ -x "/etc/init.d/APPLICATION_PACKAGE" ]; then
+                update-rc.d APPLICATION_PACKAGE defaults
+
+                if [ "START_ON_INSTALL" = "true" ]; then
+                    if which invoke-rc.d >/dev/null 2>&1; then
+                        invoke-rc.d APPLICATION_PACKAGE start
+                    else
+                        /etc/init.d/APPLICATION_PACKAGE start
+                    fi
+                fi
+	        fi
+
+        fi
+    ;;
+
+    abort-upgrade|abort-remove|abort-deconfigure)
+    ;;
+
+    *)
+        echo "postinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/template.postrm	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,44 @@
+#!/bin/sh
+# postrm script for APPLICATION_NAME
+#
+# 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 http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+case "$1" in
+    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+        if [ "$1" = "purge" ] ; then
+            if [ "SERVICE_HINT" = "true" ]; then
+                echo Uninstalling daemon
+                rm -f /etc/init.d/APPLICATION_PACKAGE
+
+                update-rc.d APPLICATION_PACKAGE remove
+            fi
+        fi
+    ;;
+
+    *)
+        echo "postrm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/template.preinst	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,35 @@
+#!/bin/sh
+# preinst script for APPLICATION_NAME
+#
+# 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 http://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
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/template.prerm	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,45 @@
+#!/bin/sh
+# prerm script for APPLICATION_NAME
+#
+# 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 http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+    remove|upgrade|deconfigure)
+        if [ "CREATE_JRE_INSTALLER" != "true" ]; then
+            echo Removing shortcut
+SECONDARY_LAUNCHERS_REMOVE
+            xdg-desktop-menu uninstall --novendor INSTALLATION_DIRECTORY/APPLICATION_FS_NAME/APPLICATION_LAUNCHER_FILENAME.desktop
+FILE_ASSOCIATION_REMOVE
+        fi
+    ;;
+
+    failed-upgrade)
+    ;;
+
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/jdk/packager/internal/resources/linux/template.spec	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,60 @@
+Summary: APPLICATION_SUMMARY
+Name: APPLICATION_PACKAGE
+Version: APPLICATION_VERSION
+Release: 1
+License: APPLICATION_LICENSE_TYPE
+Vendor: APPLICATION_VENDOR
+Prefix: INSTALLATION_DIRECTORY
+Provides: APPLICATION_PACKAGE
+Autoprov: 0
+Autoreq: 0
+PACKAGE_DEPENDENCIES
+
+#avoid ARCH subfolder
+%define _rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm
+
+#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}
+mkdir -p %{buildroot}INSTALLATION_DIRECTORY
+cp -r %{_sourcedir}/APPLICATION_FS_NAME %{buildroot}INSTALLATION_DIRECTORY
+
+%files
+APPLICATION_LICENSE_FILE
+INSTALLATION_DIRECTORY/APPLICATION_FS_NAME
+
+%post
+if [ "CREATE_JRE_INSTALLER" != "true" ]; then
+SECONDARY_LAUNCHERS_INSTALL
+    xdg-desktop-menu install --novendor INSTALLATION_DIRECTORY/APPLICATION_FS_NAME/APPLICATION_LAUNCHER_FILENAME.desktop
+FILE_ASSOCIATION_INSTALL
+fi
+
+%preun
+if [ "CREATE_JRE_INSTALLER" != "true" ]; then
+SECONDARY_LAUNCHERS_REMOVE
+    xdg-desktop-menu uninstall --novendor INSTALLATION_DIRECTORY/APPLICATION_FS_NAME/APPLICATION_LAUNCHER_FILENAME.desktop
+FILE_ASSOCIATION_REMOVE
+fi
+if [ "SERVICE_HINT" = "true" ]; then
+    if [ -x "/etc/init.d/APPLICATION_PACKAGE" ]; then
+        if [ "STOP_ON_UNINSTALL" = "true" ]; then
+            /etc/init.d/APPLICATION_PACKAGE stop
+        fi
+        /sbin/chkconfig --del APPLICATION_PACKAGE
+        rm -f /etc/init.d/APPLICATION_PACKAGE
+    fi
+fi
+
+%clean
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/classes/module-info.java.extra	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 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.
+ */
+
+
+provides jdk.packager.internal.Bundler with
+    jdk.packager.internal.linux.LinuxAppBundler,
+    jdk.packager.internal.linux.LinuxDebBundler,
+    jdk.packager.internal.linux.LinuxRpmBundler;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/linux/native/launcher/launcher.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#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 += "/libpackager.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(argc, argv) == true) {
+            result = 0;
+
+            if (stop != NULL) {
+                stop();
+            }
+        }
+
+        dlclose(library);
+    }
+
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/builders/mac/MacAppImageBuilder.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,1057 @@
+/*
+ * Copyright (c) 2015, 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.packager.internal.builders.mac;
+
+
+import jdk.packager.internal.BundlerParamInfo;
+import jdk.packager.internal.IOUtils;
+import jdk.packager.internal.Log;
+import jdk.packager.internal.Platform;
+import jdk.packager.internal.RelativeFileSet;
+import jdk.packager.internal.StandardBundlerParam;
+
+import jdk.packager.internal.Arguments;
+import jdk.packager.internal.resources.mac.MacResources;
+
+import jdk.packager.internal.builders.AbstractAppImageBuilder;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+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.math.BigInteger;
+import java.nio.file.Files;
+import java.nio.file.Path;
+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 static jdk.packager.internal.StandardBundlerParam.*;
+import static jdk.packager.internal.mac.MacBaseInstallerBundler.*;
+import static jdk.packager.internal.mac.MacAppBundler.*;
+
+
+public class MacAppImageBuilder extends AbstractAppImageBuilder {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.builders.mac.MacAppImageBuilder");
+
+    private static final String EXECUTABLE_NAME = "JavaAppLauncher";
+    private static final String LIBRARY_NAME = "libpackager.dylib";
+    private static final String TEMPLATE_BUNDLE_ICON = "GenericApp.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 javaDir;
+    private final Path resourcesDir;
+    private final Path macOSDir;
+    private final Path runtimeDir;
+    private final Path runtimeRoot;
+    private final Path mdir;
+
+    private final Map<String, ? super Object> params;
+
+    private static List<String> keyChains;
+
+    private static Map<String, String> getMacCategories() {
+        Map<String, String> map = new HashMap<>();
+        map.put("Business", "public.app-category.business");
+        map.put("Developer Tools", "public.app-category.developer-tools");
+        map.put("Education", "public.app-category.education");
+        map.put("Entertainment", "public.app-category.entertainment");
+        map.put("Finance", "public.app-category.finance");
+        map.put("Games", "public.app-category.games");
+        map.put("Graphics & Design", "public.app-category.graphics-design");
+        map.put("Healthcare & Fitness",
+                "public.app-category.healthcare-fitness");
+        map.put("Lifestyle", "public.app-category.lifestyle");
+        map.put("Medical", "public.app-category.medical");
+        map.put("Music", "public.app-category.music");
+        map.put("News", "public.app-category.news");
+        map.put("Photography", "public.app-category.photography");
+        map.put("Productivity", "public.app-category.productivity");
+        map.put("Reference", "public.app-category.reference");
+        map.put("Social Networking", "public.app-category.social-networking");
+        map.put("Sports", "public.app-category.sports");
+        map.put("Travel", "public.app-category.travel");
+        map.put("Utilities", "public.app-category.utilities");
+        map.put("Video", "public.app-category.video");
+        map.put("Weather", "public.app-category.weather");
+
+        map.put("Action Games", "public.app-category.action-games");
+        map.put("Adventure Games", "public.app-category.adventure-games");
+        map.put("Arcade Games", "public.app-category.arcade-games");
+        map.put("Board Games", "public.app-category.board-games");
+        map.put("Card Games", "public.app-category.card-games");
+        map.put("Casino Games", "public.app-category.casino-games");
+        map.put("Dice Games", "public.app-category.dice-games");
+        map.put("Educational Games", "public.app-category.educational-games");
+        map.put("Family Games", "public.app-category.family-games");
+        map.put("Kids Games", "public.app-category.kids-games");
+        map.put("Music Games", "public.app-category.music-games");
+        map.put("Puzzle Games", "public.app-category.puzzle-games");
+        map.put("Racing Games", "public.app-category.racing-games");
+        map.put("Role Playing Games", "public.app-category.role-playing-games");
+        map.put("Simulation Games", "public.app-category.simulation-games");
+        map.put("Sports Games", "public.app-category.sports-games");
+        map.put("Strategy Games", "public.app-category.strategy-games");
+        map.put("Trivia Games", "public.app-category.trivia-games");
+        map.put("Word Games", "public.app-category.word-games");
+
+        return map;
+    }
+
+    public static final BundlerParamInfo<Boolean>
+            MAC_CONFIGURE_LAUNCHER_IN_PLIST = new StandardBundlerParam<>(
+                    I18N.getString("param.configure-launcher-in-plist"),
+                    I18N.getString(
+                            "param.configure-launcher-in-plist.description"),
+                    "mac.configure-launcher-in-plist",
+                    Boolean.class,
+                    params -> Boolean.FALSE,
+                    (s, p) -> Boolean.valueOf(s));
+
+    public static final BundlerParamInfo<String> MAC_CATEGORY =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.category-name"),
+                    I18N.getString("param.category-name.description"),
+                    "mac.category",
+                    String.class,
+                    CATEGORY::fetchFrom,
+                    (s, p) -> s
+            );
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.cfbundle-name.name"),
+                    I18N.getString("param.cfbundle-name.description"),
+                    "mac.CFBundleName",
+                    String.class,
+                    params -> null,
+                    (s, p) -> s);
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_IDENTIFIER =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.cfbundle-identifier.name"),
+                    I18N.getString("param.cfbundle-identifier.description"),
+                    Arguments.CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(),
+                    String.class,
+                    IDENTIFIER::fetchFrom,
+                    (s, p) -> s);
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.cfbundle-version.name"),
+                    I18N.getString("param.cfbundle-version.description"),
+                    "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> CONFIG_ROOT =
+            new StandardBundlerParam<>(
+            I18N.getString("param.config-root.name"),
+            I18N.getString("param.config-root.description"),
+            "configRoot",
+            File.class,
+            params -> {
+                File configRoot =
+                        new File(BUILD_ROOT.fetchFrom(params), "macosx");
+                configRoot.mkdirs();
+                return configRoot;
+            },
+            (s, p) -> new File(s));
+
+    public static final BundlerParamInfo<String> DEFAULT_ICNS_ICON =
+            new StandardBundlerParam<>(
+            I18N.getString("param.default-icon-icns"),
+            I18N.getString("param.default-icon-icns.description"),
+            ".mac.default.icns",
+            String.class,
+            params -> TEMPLATE_BUNDLE_ICON,
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<File> ICON_ICNS =
+            new StandardBundlerParam<>(
+            I18N.getString("param.icon-icns.name"),
+            I18N.getString("param.icon-icns.description"),
+            "icon.icns",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".icns")) {
+                    Log.info(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<>(
+            I18N.getString("param.sign-bundle.name"),
+            I18N.getString("param.sign-bundle.description"),
+            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> config, Path imageOutDir)
+            throws IOException {
+        super(config, imageOutDir.resolve(APP_NAME.fetchFrom(config)
+                + ".app/Contents/PlugIns/Java.runtime/Contents/Home"));
+
+        Objects.requireNonNull(imageOutDir);
+
+        this.params = config;
+        this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params) + ".app");
+        this.contentsDir = root.resolve("Contents");
+        this.javaDir = contentsDir.resolve("Java");
+        this.resourcesDir = contentsDir.resolve("Resources");
+        this.macOSDir = contentsDir.resolve("MacOS");
+        this.runtimeDir = contentsDir.resolve("PlugIns/Java.runtime");
+        this.runtimeRoot = runtimeDir.resolve("Contents/Home");
+        this.mdir = runtimeRoot.resolve("lib");
+        Files.createDirectories(javaDir);
+        Files.createDirectories(resourcesDir);
+        Files.createDirectories(macOSDir);
+        Files.createDirectories(runtimeDir);
+    }
+
+    public MacAppImageBuilder(Map<String, Object> config, String jreName,
+            Path imageOutDir) throws IOException {
+        super(null, imageOutDir.resolve(jreName + "/Contents/Home"));
+
+        Objects.requireNonNull(imageOutDir);
+
+        this.params = config;
+        this.root = imageOutDir.resolve(jreName );
+        this.contentsDir = root.resolve("Contents");
+        this.javaDir = null;
+        this.resourcesDir = null;
+        this.macOSDir = null;
+        this.runtimeDir = this.root;
+        this.runtimeRoot = runtimeDir.resolve("Contents/Home");
+        this.mdir = runtimeRoot.resolve("lib");
+
+        Files.createDirectories(runtimeDir);
+    }
+
+    private void writeEntry(InputStream in, Path dstFile) throws IOException {
+        Files.createDirectories(dstFile.getParent());
+        Files.copy(in, dstFile);
+    }
+
+    // chmod ugo+x file
+    private void setExecutable(Path file) {
+        try {
+            Set<PosixFilePermission> perms =
+                    Files.getPosixFilePermissions(file);
+            perms.add(PosixFilePermission.OWNER_EXECUTE);
+            perms.add(PosixFilePermission.GROUP_EXECUTE);
+            perms.add(PosixFilePermission.OTHERS_EXECUTE);
+            Files.setPosixFilePermissions(file, perms);
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    private static void createUtf8File(File file, String content)
+        throws IOException {
+        try (OutputStream fout = new FileOutputStream(file);
+             Writer output = new OutputStreamWriter(fout, "UTF-8")) {
+            output.write(content);
+        }
+    }
+
+    @Override
+    protected String getCacheLocation(Map<String, ? super Object> params) {
+        return "$CACHEDIR/";
+    }
+
+    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 InputStream getResourceAsStream(String name) {
+        return MacResources.class.getResourceAsStream(name);
+    }
+
+    @Override
+    public void prepareApplicationFiles() throws IOException {
+        File f;
+
+        // Generate PkgInfo
+        File pkgInfoFile = new File(contentsDir.toFile(), "PkgInfo");
+        pkgInfoFile.createNewFile();
+        writePkgInfo(pkgInfoFile);
+
+        Path executable = macOSDir.resolve(getLauncherName(params));
+
+        try (InputStream is_launcher = getResourceAsStream("papplauncher");
+             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 launcher config
+        writeCfgFile(params,
+                new File(root.toFile(), getLauncherCfgName(params)),
+                "$APPDIR/PlugIns/Java.runtime");
+
+        // Copy class path entries to Java folder
+        copyClassPathEntries(javaDir);
+
+        /*********** Take care of "config" files *******/
+        File icon = ICON_ICNS.fetchFrom(params);
+        InputStream in = locateResource(
+                "package/macosx/" + APP_NAME.fetchFrom(params) + ".icns",
+                "icon",
+                DEFAULT_ICNS_ICON.fetchFrom(params),
+                icon,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        Files.copy(in,
+                resourcesDir.resolve(APP_NAME.fetchFrom(params) + ".icns"));
+
+        // copy file association icons
+        for (Map<String, ?
+                super Object> fa : FILE_ASSOCIATIONS.fetchFrom(params)) {
+            f = FA_ICON.fetchFrom(fa);
+            if (f != null && f.exists()) {
+                try (InputStream in2 = new FileInputStream(f)) {
+                    Files.copy(in2, resourcesDir.resolve(f.getName()));
+                }
+
+            }
+        }
+
+        copyRuntimeFiles();
+        sign();
+    }
+
+    @Override
+    public void prepareServerJreFiles() throws IOException {
+        copyRuntimeFiles();
+        sign();
+    }
+
+    private void copyRuntimeFiles() throws IOException {
+        // Generate Info.plist
+        writeInfoPlist(contentsDir.resolve("Info.plist").toFile());
+
+        // generate java runtime info.plist
+        writeRuntimeInfoPlist(
+                runtimeDir.resolve("Contents/Info.plist").toFile());
+
+        // copy library
+        Path runtimeMacOSDir = Files.createDirectories(
+                runtimeDir.resolve("Contents/MacOS"));
+        Files.copy(runtimeRoot.resolve("lib/jli/libjli.dylib"),
+                runtimeMacOSDir.resolve("libjli.dylib"));
+    }
+
+    private void sign() 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> p) {
+        return "Contents/Java/" + APP_NAME.fetchFrom(p) + ".cfg";
+    }
+
+    private void copyClassPathEntries(Path javaDirectory) 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.info(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) throws IOException {
+        Map<String, String> data = new HashMap<>();
+        String identifier = Arguments.CREATE_JRE_INSTALLER.fetchFrom(params) ?
+                MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) :
+                "com.oracle.java." + MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params);
+        data.put("CF_BUNDLE_IDENTIFIER", identifier);
+        String name = Arguments.CREATE_JRE_INSTALLER.fetchFrom(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));
+
+        Writer w = new BufferedWriter(new FileWriter(file));
+        w.write(preprocessTextResource(
+                "package/macosx/Runtime-Info.plist",
+                I18N.getString("resource.runtime-info-plist"),
+                TEMPLATE_RUNTIME_INFO_PLIST,
+                data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params)));
+        w.close();
+    }
+
+    private void writeInfoPlist(File file) 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_JAVA_RUNTIME_NAME", "$APPDIR/PlugIns/Java.runtime");
+        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");
+        data.put("DEPLOY_BUNDLE_CATEGORY", MAC_CATEGORY.fetchFrom(params));
+
+        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));
+        }
+
+        data.put("DEPLOY_PREFERENCES_ID",
+                PREFERENCES_ID.fetchFrom(params).toLowerCase());
+
+        StringBuilder sb = new StringBuilder();
+        List<String> jvmOptions = JVM_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";
+        }
+
+        Map<String, String> jvmProps = JVM_PROPERTIES.fetchFrom(params);
+        for (Map.Entry<String, String> entry : jvmProps.entrySet()) {
+            sb.append(newline)
+                    .append("    <string>-D")
+                    .append(entry.getKey())
+                    .append("=")
+                    .append(entry.getValue())
+                    .append("</string>");
+            newline = "\n";
+        }
+
+        String preloader = PRELOADER_CLASS.fetchFrom(params);
+        if (preloader != null) {
+            sb.append(newline)
+                    .append("    <string>-Djavafx.preloader=")
+                    .append(preloader)
+                    .append("</string>");
+        }
+
+        data.put("DEPLOY_JVM_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 = "";
+        sb = new StringBuilder();
+        Map<String, String> overridableJVMOptions =
+                USER_JVM_OPTIONS.fetchFrom(params);
+        for (Map.Entry<String, String> arg : overridableJVMOptions.entrySet()) {
+            sb.append(newline)
+                    .append("      <key>")
+                    .append(arg.getKey())
+                    .append("</key>\n")
+                    .append("      <string>")
+                    .append(arg.getValue())
+                    .append("</string>");
+            newline = "\n";
+        }
+        data.put("DEPLOY_JVM_USER_OPTIONS", sb.toString());
+
+
+        data.put("DEPLOY_LAUNCHER_CLASS", MAIN_CLASS.fetchFrom(params));
+
+        StringBuilder macroedPath = new StringBuilder();
+        for (String s : CLASSPATH.fetchFrom(params).split("[ ;:]+")) {
+            macroedPath.append(s);
+            macroedPath.append(":");
+        }
+        macroedPath.deleteCharAt(macroedPath.length() - 1);
+
+        data.put("DEPLOY_APP_CLASSPATH", macroedPath.toString());
+
+        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.info(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); //TODO FA_ICON_ICNS
+
+            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);
+
+
+        Writer w = new BufferedWriter(new FileWriter(file));
+        w.write(preprocessTextResource(
+                //MAC_BUNDLER_PREFIX + getConfig_InfoPlist(params).getName(),
+                "package/macosx/Info.plist",
+                I18N.getString("resource.app-info-plist"),
+                TEMPLATE_INFO_PLIST_LITE,
+                data, VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params)));
+        w.close();
+    }
+
+    private void writePkgInfo(File file) throws IOException {
+        //hardcoded as it does not seem we need to change it ever
+        String signature = "????";
+
+        try (Writer out = new BufferedWriter(new FileWriter(file))) {
+            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, ECHO_MODE.fetchFrom(params));
+    }
+
+    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, ECHO_MODE.fetchFrom(params));
+    }
+
+    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
+        Files.walk(appLocation)
+                // fix permissions
+                .peek(path -> {
+                    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.debug(e);
+                    }
+                })
+                .filter(p -> Files.isRegularFile(p) &&
+                        !(p.toString().contains("/Contents/MacOS/libjli.dylib")
+                        || p.toString().contains(
+                                "/Contents/MacOS/JavaAppletPlugin")
+                        || p.toString().endsWith(appExecutable))
+                ).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 {
+                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, ECHO_MODE.fetchFrom(params));
+
+                    Files.setPosixFilePermissions(p, oldPermissions);
+                } catch (IOException ioe) {
+                    toThrow.set(ioe);
+                }
+            }
+        });
+
+        IOException ioe = toThrow.get();
+        if (ioe != null) {
+            throw ioe;
+        }
+
+        // sign all plugins 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, ECHO_MODE.fetchFrom(params));
+
+                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, ECHO_MODE.fetchFrom(params));
+            } catch (IOException e) {
+                toThrow.set(e);
+            }
+        };
+
+        Path pluginsPath = appLocation.resolve("Contents/PlugIns");
+        if (Files.isDirectory(pluginsPath)) {
+            Files.list(pluginsPath)
+                    .forEach(signIdentifiedByPList);
+
+            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, ECHO_MODE.fetchFrom(params));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/mac/MacAppBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.mac;
+
+import jdk.packager.internal.AbstractImageBundler;
+import jdk.packager.internal.BundlerParamInfo;
+import jdk.packager.internal.ConfigException;
+import jdk.packager.internal.EnumeratedBundlerParam;
+import jdk.packager.internal.IOUtils;
+import jdk.packager.internal.Log;
+import jdk.packager.internal.Platform;
+import jdk.packager.internal.StandardBundlerParam;
+import jdk.packager.internal.Arguments;
+import jdk.packager.internal.UnsupportedPlatformException;
+import jdk.packager.internal.builders.mac.MacAppImageBuilder;
+import jdk.packager.internal.resources.mac.MacResources;
+
+import jdk.packager.internal.JLinkBundlerHelper;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ResourceBundle;
+
+import static jdk.packager.internal.StandardBundlerParam.*;
+import static jdk.packager.internal.mac.MacBaseInstallerBundler.*;
+import jdk.packager.internal.builders.AbstractAppImageBuilder;
+
+public class MacAppBundler extends AbstractImageBundler {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle(
+                    "jdk.packager.internal.resources.mac.MacAppBundler");
+
+    public final static String MAC_BUNDLER_PREFIX =
+            BUNDLER_PREFIX + "macosx" + File.separator;
+
+    private static final String TEMPLATE_BUNDLE_ICON = "GenericApp.icns";
+
+    private static Map<String, String> getMacCategories() {
+        Map<String, String> map = new HashMap<>();
+        map.put("Business", "public.app-category.business");
+        map.put("Developer Tools", "public.app-category.developer-tools");
+        map.put("Education", "public.app-category.education");
+        map.put("Entertainment", "public.app-category.entertainment");
+        map.put("Finance", "public.app-category.finance");
+        map.put("Games", "public.app-category.games");
+        map.put("Graphics & Design", "public.app-category.graphics-design");
+        map.put("Healthcare & Fitness",
+                "public.app-category.healthcare-fitness");
+        map.put("Lifestyle", "public.app-category.lifestyle");
+        map.put("Medical", "public.app-category.medical");
+        map.put("Music", "public.app-category.music");
+        map.put("News", "public.app-category.news");
+        map.put("Photography", "public.app-category.photography");
+        map.put("Productivity", "public.app-category.productivity");
+        map.put("Reference", "public.app-category.reference");
+        map.put("Social Networking", "public.app-category.social-networking");
+        map.put("Sports", "public.app-category.sports");
+        map.put("Travel", "public.app-category.travel");
+        map.put("Utilities", "public.app-category.utilities");
+        map.put("Video", "public.app-category.video");
+        map.put("Weather", "public.app-category.weather");
+
+        map.put("Action Games", "public.app-category.action-games");
+        map.put("Adventure Games", "public.app-category.adventure-games");
+        map.put("Arcade Games", "public.app-category.arcade-games");
+        map.put("Board Games", "public.app-category.board-games");
+        map.put("Card Games", "public.app-category.card-games");
+        map.put("Casino Games", "public.app-category.casino-games");
+        map.put("Dice Games", "public.app-category.dice-games");
+        map.put("Educational Games", "public.app-category.educational-games");
+        map.put("Family Games", "public.app-category.family-games");
+        map.put("Kids Games", "public.app-category.kids-games");
+        map.put("Music Games", "public.app-category.music-games");
+        map.put("Puzzle Games", "public.app-category.puzzle-games");
+        map.put("Racing Games", "public.app-category.racing-games");
+        map.put("Role Playing Games", "public.app-category.role-playing-games");
+        map.put("Simulation Games", "public.app-category.simulation-games");
+        map.put("Sports Games", "public.app-category.sports-games");
+        map.put("Strategy Games", "public.app-category.strategy-games");
+        map.put("Trivia Games", "public.app-category.trivia-games");
+        map.put("Word Games", "public.app-category.word-games");
+
+        return map;
+    }
+
+    public static final EnumeratedBundlerParam<String> MAC_CATEGORY =
+            new EnumeratedBundlerParam<>(
+                    I18N.getString("param.category-name"),
+                    I18N.getString("param.category-name.description"),
+                    Arguments.CLIOptions.MAC_APP_STORE_CATEGORY.getId(),
+                    String.class,
+                    params -> params.containsKey(CATEGORY.getID())
+                            ? CATEGORY.fetchFrom(params)
+                            : "Unknown",
+                    (s, p) -> s,
+                    getMacCategories(),
+                    false //strict - for MacStoreBundler this should be strict
+            );
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.cfbundle-name.name"),
+                    I18N.getString("param.cfbundle-name.description"),
+                    Arguments.CLIOptions.MAC_BUNDLE_NAME.getId(),
+                    String.class,
+                    params -> null,
+                    (s, p) -> s);
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_IDENTIFIER =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.cfbundle-identifier.name"),
+                    I18N.getString("param.cfbundle-identifier.description"),
+                    Arguments.CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(),
+                    String.class,
+                    IDENTIFIER::fetchFrom,
+                    (s, p) -> s);
+
+    public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.cfbundle-version.name"),
+                    I18N.getString("param.cfbundle-version.description"),
+                    "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> CONFIG_ROOT =
+            new StandardBundlerParam<>(
+            I18N.getString("param.config-root.name"),
+            I18N.getString("param.config-root.description"),
+            "configRoot",
+            File.class,
+            params -> {
+                File configRoot =
+                        new File(BUILD_ROOT.fetchFrom(params), "macosx");
+                configRoot.mkdirs();
+                return configRoot;
+            },
+            (s, p) -> new File(s));
+
+    public static final BundlerParamInfo<String> DEFAULT_ICNS_ICON =
+            new StandardBundlerParam<>(
+            I18N.getString("param.default-icon-icns"),
+            I18N.getString("param.default-icon-icns.description"),
+            ".mac.default.icns",
+            String.class,
+            params -> TEMPLATE_BUNDLE_ICON,
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<String> DEVELOPER_ID_APP_SIGNING_KEY =
+            new StandardBundlerParam<>(
+            I18N.getString("param.signing-key-developer-id-app.name"),
+            I18N.getString("param.signing-key-developer-id-app.description"),
+            "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,
+                                VERBOSE.fetchFrom(params));
+
+                        if (!certificate.isValid()) {
+                            Log.info(MessageFormat.format(I18N.getString(
+                                    "error.certificate.expired"), result));
+                        }
+                    }
+
+                    return result;
+                },
+            (s, p) -> s);
+
+    public static final BundlerParamInfo<String> BUNDLE_ID_SIGNING_PREFIX =
+            new StandardBundlerParam<>(
+            I18N.getString("param.bundle-id-signing-prefix.name"),
+            I18N.getString("param.bundle-id-signing-prefix.description"),
+            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<>(
+            I18N.getString("param.icon-icns.name"),
+            I18N.getString("param.icon-icns.description"),
+            "icon.icns",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".icns")) {
+                    Log.info(MessageFormat.format(
+                            I18N.getString("message.icon-not-icns"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+    public MacAppBundler() {
+        super();
+        baseResourceLoader = MacResources.class;
+    }
+
+    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 UnsupportedPlatformException, ConfigException {
+        try {
+            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"
+    public boolean doValidate(Map<String, ? super Object> p)
+            throws UnsupportedPlatformException, ConfigException {
+        if (Platform.getPlatform() != Platform.MAC) {
+            throw new UnsupportedPlatformException();
+        }
+
+        imageBundleValidation(p);
+
+        if (StandardBundlerParam.getPredefinedAppImage(p) != null) {
+            return true;
+        }
+
+        // validate short version
+        if (!validCFBundleVersion(MAC_CF_BUNDLE_VERSION.fetchFrom(p))) {
+            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(p)).orElse(Boolean.FALSE)) {
+            String signingIdentity = DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(p);
+            if (signingIdentity == null) {
+                throw new ConfigException(
+                        I18N.getString("error.explicit-sign-no-cert"),
+                        I18N.getString("error.explicit-sign-no-cert.advice"));
+            }
+        }
+
+        return true;
+    }
+
+    private File getConfig_InfoPlist(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params), "Info.plist");
+    }
+
+    private File getConfig_Icon(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + ".icns");
+    }
+
+    File doBundle(Map<String, ? super Object> p, File outputDirectory,
+            boolean dependentTask) {
+        if (Arguments.CREATE_JRE_INSTALLER.fetchFrom(p)) {
+            return doJreBundle(p, outputDirectory, dependentTask);
+        } else {
+            return doAppBundle(p, outputDirectory, dependentTask);
+        }
+    }
+
+    File doJreBundle(Map<String, ? super Object> p,
+            File outputDirectory, boolean dependentTask) {
+        try {
+            File rootDirectory = createRoot(p, outputDirectory, dependentTask,
+                    APP_NAME.fetchFrom(p));
+            AbstractAppImageBuilder appBuilder = new MacAppImageBuilder(p,
+                    APP_NAME.fetchFrom(p), outputDirectory.toPath());
+            File predefined = PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
+            if (predefined == null ) {
+                JLinkBundlerHelper.generateServerJre(p, appBuilder);
+            } else {
+                return predefined;
+            }
+            return rootDirectory;
+        } catch (IOException ex) {
+            Log.info(ex.toString());
+            Log.verbose(ex);
+            return null;
+        } catch (Exception ex) {
+            Log.info("Exception: "+ex);
+            Log.debug(ex);
+            return null;
+        }
+    }
+
+    File doAppBundle(Map<String, ? super Object> p, File outputDirectory,
+            boolean dependentTask) {
+        try {
+            File rootDirectory = createRoot(p, outputDirectory, dependentTask,
+                    APP_NAME.fetchFrom(p) + ".app");
+            AbstractAppImageBuilder appBuilder =
+                    new MacAppImageBuilder(p, outputDirectory.toPath());
+            if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {
+                JLinkBundlerHelper.execute(p, appBuilder);
+            } else {
+                StandardBundlerParam.copyPredefinedRuntimeImage(p, appBuilder);
+            }
+            return rootDirectory;
+        } catch (IOException ex) {
+            Log.info(ex.toString());
+            Log.verbose(ex);
+            return null;
+        } catch (Exception ex) {
+            Log.info("Exception: "+ex);
+            Log.debug(ex);
+            return null;
+        }
+    }
+
+    private File createRoot(Map<String, ? super Object> p,
+            File outputDirectory, boolean dependentTask, String name)
+            throws IOException {
+        if (!outputDirectory.isDirectory() && !outputDirectory.mkdirs()) {
+            throw new RuntimeException(MessageFormat.format(I18N.getString(
+                    "error.cannot-create-output-dir"),
+                    outputDirectory.getAbsolutePath()));
+        }
+        if (!outputDirectory.canWrite()) {
+            throw new RuntimeException(MessageFormat.format(I18N.getString(
+                    "error.cannot-write-to-output-dir"),
+                    outputDirectory.getAbsolutePath()));
+        }
+
+        // Create directory structure
+        File rootDirectory = new File(outputDirectory, name);
+        IOUtils.deleteRecursive(rootDirectory);
+        rootDirectory.mkdirs();
+
+        if (!dependentTask) {
+            Log.info(MessageFormat.format(I18N.getString(
+                    "message.creating-app-bundle"),
+                    rootDirectory.getAbsolutePath()));
+        }
+
+        if (!p.containsKey(JLinkBundlerHelper.JLINK_BUILDER.getID())) {
+            p.put(JLinkBundlerHelper.JLINK_BUILDER.getID(),
+                    "macapp-image-builder");
+        }
+        return rootDirectory;
+    }
+
+    public void cleanupConfigFiles(Map<String, ? super Object> params) {
+        //Since building the app can be bypassed, make sure configRoot was set
+        if (CONFIG_ROOT.fetchFrom(params) != null
+                && !StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            getConfig_Icon(params).delete();
+            getConfig_InfoPlist(params).delete();
+        }
+    }
+
+    /////////////////////////////////////////////////////////////////////////
+    // Implement Bundler
+    /////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String getName() {
+        return I18N.getString("bundler.name");
+    }
+
+    @Override
+    public String getDescription() {
+        return I18N.getString("bundler.description");
+    }
+
+    @Override
+    public String getID() {
+        return "mac.app";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "IMAGE";
+    }
+
+    @Override
+    public Collection<BundlerParamInfo<?>> getBundleParameters() {
+        return getAppBundleParameters();
+    }
+
+    public static Collection<BundlerParamInfo<?>> getAppBundleParameters() {
+        return Arrays.asList(
+                APP_NAME,
+                APP_RESOURCES,
+                ARGUMENTS,
+                BUNDLE_ID_SIGNING_PREFIX,
+                CLASSPATH,
+                DEVELOPER_ID_APP_SIGNING_KEY,
+                ICON_ICNS,
+                JVM_OPTIONS,
+                MAC_CATEGORY,
+                MAC_CF_BUNDLE_IDENTIFIER,
+                MAC_CF_BUNDLE_NAME,
+                MAC_CF_BUNDLE_VERSION,
+                MAIN_CLASS,
+                MAIN_JAR,
+                PREFERENCES_ID,
+                SIGNING_KEYCHAIN,
+                USER_JVM_OPTIONS,
+                VERSION,
+                VERBOSE
+        );
+    }
+
+
+    @Override
+    public File execute(Map<String, ? super Object> params,
+            File outputParentDir) {
+        return doBundle(params, outputParentDir, false);
+    }
+
+    @Override    
+    public boolean supported() {
+        return Platform.getPlatform() == Platform.MAC;
+    }
+
+//    private void createLauncherForEntryPoint(Map<String, ? super Object> p,
+//            File rootDirectory) throws IOException {
+//        prepareConfigFiles(p);
+//
+//        if (LAUNCHER_CFG_FORMAT.fetchFrom(p).equals(CFG_FORMAT_PROPERTIES)) {
+//            writeCfgFile(p, rootDirectory);
+//        } else {
+//            writeCfgFile(p, new File(rootDirectory, getLauncherCfgName(p)),
+//                    "$APPDIR/PlugIns/Java.runtime");
+//        }
+//
+//        // Copy executable root folder
+//        File executableFile = new File(rootDirectory,
+//                "Contents/MacOS/" + getLauncherName(p));
+//        IOUtils.copyFromURL(
+//                RAW_EXECUTABLE_URL.fetchFrom(p),
+//                executableFile);
+//        executableFile.setExecutable(true, false);
+//
+//    }
+//
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/mac/MacAppStoreBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal.mac;
+
+import jdk.packager.internal.BundlerParamInfo;
+import jdk.packager.internal.StandardBundlerParam;
+import jdk.packager.internal.Arguments;
+import jdk.packager.internal.Log;
+import jdk.packager.internal.ConfigException;
+import jdk.packager.internal.IOUtils;
+import jdk.packager.internal.Platform;
+import jdk.packager.internal.UnsupportedPlatformException;
+import jdk.packager.internal.builders.mac.MacAppImageBuilder;
+import jdk.packager.internal.resources.mac.MacResources;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ResourceBundle;
+
+import static jdk.packager.internal.StandardBundlerParam.*;
+import static jdk.packager.internal.mac.MacAppBundler.*;
+
+public class MacAppStoreBundler extends MacBaseInstallerBundler {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.mac.MacAppStoreBundler");
+
+    private static final String TEMPLATE_BUNDLE_ICON_HIDPI =
+            "GenericAppHiDPI.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<>(
+            I18N.getString("param.signing-key-app.name"),
+            I18N.getString("param.signing-key-app.description"),
+            "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,
+                                VERBOSE.fetchFrom(params));
+
+                        if (!certificate.isValid()) {
+                            Log.info(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<>(
+            I18N.getString("param.signing-key-pkg.name"),
+            I18N.getString("param.signing-key-pkg.description"),
+            "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, VERBOSE.fetchFrom(params));
+
+                        if (!certificate.isValid()) {
+                            Log.info(MessageFormat.format(
+                                    I18N.getString("error.certificate.expired"),
+                                    result));
+                        }
+                    }
+
+                    return result;
+                },
+            (s, p) -> s);
+
+    public static final StandardBundlerParam<File> MAC_APP_STORE_ENTITLEMENTS  =
+            new StandardBundlerParam<>(
+            I18N.getString("param.mac-app-store-entitlements.name"),
+            I18N.getString("param.mac-app-store-entitlements.description"),
+            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<> (
+            I18N.getString("param.installer-suffix.name"),
+            I18N.getString("param.installer-suffix.description"),
+            "mac.app-store.installerName.suffix",
+            String.class,
+            params -> "-MacAppStore",
+            (s, p) -> s);
+
+    public MacAppStoreBundler() {
+        super();
+        baseResourceLoader = MacResources.class;
+    }
+
+    //@Override
+    public File bundle(Map<String, ? super Object> p, File outdir) {
+        Log.info(MessageFormat.format(I18N.getString("message.building-bundle"),
+                APP_NAME.fetchFrom(p)));
+        if (!outdir.isDirectory() && !outdir.mkdirs()) {
+            throw new RuntimeException(MessageFormat.format(I18N.getString(
+                    "error.cannot-create-output-dir"),
+                     outdir.getAbsolutePath()));
+        }
+        if (!outdir.canWrite()) {
+            throw new RuntimeException(MessageFormat.format(I18N.getString(
+                    "error.cannot-write-to-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+
+        // first, load in some overrides
+        // icns needs @2 versions, so load in the @2 default
+        p.put(DEFAULT_ICNS_ICON.getID(), TEMPLATE_BUNDLE_ICON_HIDPI);
+
+        // next we need to change the jdk/jre stripping to strip gstreamer
+//        p.put(MAC_RULES.getID(), createMacAppStoreRuntimeRules(p));
+
+        // now we create the app
+        File appImageDir = APP_IMAGE_BUILD_ROOT.fetchFrom(p);
+        try {
+            appImageDir.mkdirs();
+
+            try {
+                MacAppImageBuilder.addNewKeychain(p);
+            } catch (InterruptedException e) {
+                Log.error(e.getMessage());
+            }
+            // first, make sure we don't use the local signing key
+            p.put(DEVELOPER_ID_APP_SIGNING_KEY.getID(), null);
+            File appLocation = prepareAppBundle(p, false);
+
+            prepareEntitlements(p);
+
+            String signingIdentity = MAC_APP_STORE_APP_SIGNING_KEY.fetchFrom(p);
+            String identifierPrefix = BUNDLE_ID_SIGNING_PREFIX.fetchFrom(p);
+            String entitlementsFile = getConfig_Entitlements(p).toString();
+            String inheritEntitlements =
+                    getConfig_Inherit_Entitlements(p).toString();
+
+            MacAppImageBuilder.signAppBundle(p, appLocation.toPath(),
+                    signingIdentity, identifierPrefix,
+                    entitlementsFile, inheritEntitlements);
+            MacAppImageBuilder.restoreKeychainList(p);
+
+            ProcessBuilder pb;
+
+            // create the final pkg file
+            File finalPKG = new File(outdir, INSTALLER_NAME.fetchFrom(p)
+                    + INSTALLER_SUFFIX.fetchFrom(p)
+                    + ".pkg");
+            outdir.mkdirs();
+
+            String installIdentify =
+                    MAC_APP_STORE_PKG_SIGNING_KEY.fetchFrom(p);
+
+            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(p);
+            if (keychainName != null && !keychainName.isEmpty()) {
+                buildOptions.add("--keychain");
+                buildOptions.add(keychainName);
+            }
+            buildOptions.add(finalPKG.getAbsolutePath());
+
+            pb = new ProcessBuilder(buildOptions);
+
+            IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+            return finalPKG;
+        } catch (Exception ex) {
+            Log.info("App Store Ready Bundle failed : " + ex.getMessage());
+            ex.printStackTrace();
+            Log.debug(ex);
+            return null;
+        } finally {
+            try {
+                if (appImageDir != null &&
+                       PREDEFINED_APP_IMAGE.fetchFrom(p) == null &&
+                       (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ||
+                       !Arguments.CREATE_JRE_INSTALLER.fetchFrom(p)) &&
+                       !Log.isDebug()) {
+                    IOUtils.deleteRecursive(appImageDir);
+                } else if (appImageDir != null) {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "mesasge.intermediate-bundle-location"),
+                            appImageDir.getAbsolutePath()));
+                }
+                if (!StandardBundlerParam.ECHO_MODE.fetchFrom(p)) {
+                    //cleanup
+                    cleanupConfigFiles(p);
+                } else {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "message.config-save-location"),
+                            CONFIG_ROOT.fetchFrom(p).getAbsolutePath()));
+                }
+            } catch (IOException ex) {
+                //noinspection ReturnInsideFinallyBlock
+                Log.debug(ex.getMessage());
+                return null;
+            }
+        }
+    }
+
+    protected void cleanupConfigFiles(Map<String, ? super Object> params) {
+        if(!StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            if (getConfig_Entitlements(params) != null) {
+                getConfig_Entitlements(params).delete();
+            }
+            if (getConfig_Inherit_Entitlements(params) != null) {
+                getConfig_Inherit_Entitlements(params).delete();
+            }
+            if (PREDEFINED_APP_IMAGE.fetchFrom(params) == null) {
+                APP_BUNDLER.fetchFrom(params).cleanupConfigFiles(params);
+            }
+        }
+    }
+
+    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 {
+        File entitlements = MAC_APP_STORE_ENTITLEMENTS.fetchFrom(params);
+        if (entitlements == null || !entitlements.exists()) {
+            fetchResource(getEntitlementsFileName(params),
+                    I18N.getString("resource.mac-app-store-entitlements"),
+                    DEFAULT_ENTITLEMENTS,
+                    getConfig_Entitlements(params),
+                    VERBOSE.fetchFrom(params),
+                    DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        } else {
+            fetchResource(getEntitlementsFileName(params),
+                    I18N.getString("resource.mac-app-store-entitlements"),
+                    entitlements,
+                    getConfig_Entitlements(params),
+                    VERBOSE.fetchFrom(params),
+                    DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        }
+        fetchResource(getInheritEntitlementsFileName(params),
+                I18N.getString("resource.mac-app-store-inherit-entitlements"),
+                DEFAULT_INHERIT_ENTITLEMENTS,
+                getConfig_Inherit_Entitlements(params),
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+    }
+
+    private String getEntitlementsFileName(Map<String, ? super Object> params) {
+        return MAC_BUNDLER_PREFIX+ APP_NAME.fetchFrom(params) + ".entitlements";
+    }
+
+    private String getInheritEntitlementsFileName(
+            Map<String, ? super Object> params) {
+        return MAC_BUNDLER_PREFIX + APP_NAME.fetchFrom(params)
+                + "_Inherit.entitlements";
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////
+    // Implement Bundler
+    ///////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String getName() {
+        return I18N.getString("bundler.name");
+    }
+
+    @Override
+    public String getDescription() {
+        return I18N.getString("bundler.description");
+    }
+
+    @Override
+    public String getID() {
+        return "mac.appStore";
+    }
+
+    @Override
+    public Collection<BundlerParamInfo<?>> getBundleParameters() {
+        Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
+        results.addAll(getAppBundleParameters());
+        results.addAll(getMacAppStoreBundleParameters());
+        return results;
+    }
+
+    public Collection<BundlerParamInfo<?>> getMacAppStoreBundleParameters() {
+        Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
+
+        results.addAll(getAppBundleParameters());
+        results.remove(DEVELOPER_ID_APP_SIGNING_KEY);
+        results.addAll(Arrays.asList(
+                INSTALLER_SUFFIX,
+                MAC_APP_STORE_APP_SIGNING_KEY,
+                MAC_APP_STORE_ENTITLEMENTS,
+                MAC_APP_STORE_PKG_SIGNING_KEY,
+                SIGNING_KEYCHAIN
+        ));
+
+        return results;
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws UnsupportedPlatformException, ConfigException {
+        try {
+            if (Platform.getPlatform() != Platform.MAC) {
+                throw new UnsupportedPlatformException();
+            }
+
+            if (params == null) {
+                throw new ConfigException(
+                        I18N.getString("error.parameters-null"),
+                        I18N.getString("error.parameters-null.advice"));
+            }
+
+            // hdiutil is always available so there's no need to test for
+            // availability.
+            // run basic validation to ensure requirements are met
+
+            // TODO Mac App Store apps cannot use the system runtime
+
+            // 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) {
+        return bundle(params, outputParentDir);
+    }
+    
+    @Override    
+    public boolean supported() {
+        return !Arguments.isJreInstaller() && 
+                Platform.getPlatform() == Platform.MAC;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/mac/MacBaseInstallerBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal.mac;
+
+import jdk.packager.internal.AbstractBundler;
+import jdk.packager.internal.BundlerParamInfo;
+import jdk.packager.internal.StandardBundlerParam;
+import jdk.packager.internal.Arguments;
+import jdk.packager.internal.Log;
+import jdk.packager.internal.ConfigException;
+import jdk.packager.internal.IOUtils;
+import jdk.packager.internal.Platform;
+import jdk.packager.internal.UnsupportedPlatformException;
+
+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.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+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.packager.internal.StandardBundlerParam.*;
+
+public abstract class MacBaseInstallerBundler extends AbstractBundler {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle(
+                "jdk.packager.internal.resources.mac.MacBaseInstallerBundler");
+
+    //This could be generalized more to be for any type of Image Bundler
+    public static final BundlerParamInfo<MacAppBundler> APP_BUNDLER =
+            new StandardBundlerParam<>(
+            I18N.getString("param.app-bundler.name"),
+            I18N.getString("param.app-bundle.description"),
+            "mac.app.bundler",
+            MacAppBundler.class,
+            params -> new MacAppBundler(),
+            (s, p) -> null);
+
+    public final BundlerParamInfo<File> APP_IMAGE_BUILD_ROOT =
+            new StandardBundlerParam<>(
+            I18N.getString("param.app-image-build-root.name"),
+            I18N.getString("param.app-image-build-root.description"),
+            "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 final BundlerParamInfo<File> DAEMON_IMAGE_BUILD_ROOT =
+            new StandardBundlerParam<>(
+            I18N.getString("param.daemon-image-build-root.name"),
+            I18N.getString("param.daemon-image-build-root.description"),
+            "mac.daemon.image",
+            File.class,
+            params -> {
+                File imageDir = IMAGES_ROOT.fetchFrom(params);
+                if (!imageDir.exists()) imageDir.mkdirs();
+                return new File(imageDir, getID()+ ".daemon");
+            },
+            (s, p) -> new File(s));
+
+
+    public static final BundlerParamInfo<File> CONFIG_ROOT =
+            new StandardBundlerParam<>(
+            I18N.getString("param.config-root.name"),
+            I18N.getString("param.config-root.description"),
+            "configRoot",
+            File.class,
+            params -> {
+                File imagesRoot =
+                        new File(BUILD_ROOT.fetchFrom(params), "macosx");
+                imagesRoot.mkdirs();
+                return imagesRoot;
+            },
+            (s, p) -> null);
+
+    public static final BundlerParamInfo<String> SIGNING_KEY_USER =
+            new StandardBundlerParam<>(
+            I18N.getString("param.signing-key-name.name"),
+            I18N.getString("param.signing-key-name.description"),
+            Arguments.CLIOptions.MAC_SIGNING_KEY_NAME.getId(),
+            String.class,
+            params -> "",
+            null);
+
+    public static final BundlerParamInfo<String> SIGNING_KEYCHAIN =
+            new StandardBundlerParam<>(
+            I18N.getString("param.signing-keychain.name"),
+            I18N.getString("param.signing-keychain.description"),
+            Arguments.CLIOptions.MAC_SIGNING_KEYCHAIN.getId(),
+            String.class,
+            params -> "",
+            null);
+
+    public static final BundlerParamInfo<String> INSTALLER_NAME =
+            new StandardBundlerParam<> (
+            I18N.getString("param.installer-name.name"),
+            I18N.getString("param.installer-name.description"),
+            "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, UnsupportedPlatformException {
+        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"));
+            }
+            if (IDENTIFIER.fetchFrom(params) == null) {
+                throw new ConfigException(
+                        I18N.getString("message.app-image-requires-identifier"),
+                        I18N.getString(
+                            "message.app-image-requires-identifier.advice"));
+            }
+        } else {
+            APP_BUNDLER.fetchFrom(params).doValidate(params);
+        }
+    }
+
+    protected File prepareAppBundle(
+            Map<String, ? super Object> p, boolean pkg) {
+        File predefinedImage = StandardBundlerParam.getPredefinedAppImage(p);
+        if (predefinedImage != null) {
+            return predefinedImage;
+        }
+        File appImageRoot = APP_IMAGE_BUILD_ROOT.fetchFrom(p);
+        if (pkg) {
+            // create pkg in dmg
+            return new MacPkgBundler().bundle(p, appImageRoot);
+        } else {
+            return APP_BUNDLER.fetchFrom(p).doBundle(p, appImageRoot, true);
+        }
+    }
+
+    @Override
+    public Collection<BundlerParamInfo<?>> getBundleParameters() {
+        Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
+
+        results.addAll(MacAppBundler.getAppBundleParameters());
+        results.addAll(Arrays.asList(
+                APP_BUNDLER,
+                CONFIG_ROOT,
+                APP_IMAGE_BUILD_ROOT,
+                PREDEFINED_APP_IMAGE
+        ));
+
+        return results;
+    }
+
+    @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, verbose, false, ps);
+            Pattern p = Pattern.compile("\"alis\"<blob>=\"([^\"]+)\"");
+            Matcher m = p.matcher(baos.toString());
+            if (!m.find()) {
+                Log.info("Did not find a key matching '" + key + "'");
+                return null;
+            }
+            String matchedKey = m.group(1);
+            if (m.find()) {
+                Log.info("Found more than one key matching '"  + key + "'");
+                return null;
+            }
+            Log.debug("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.packager/macosx/classes/jdk/packager/internal/mac/MacCertificate.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2016, 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.packager.internal.mac;
+
+import jdk.packager.internal.IOUtils;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+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;
+
+final public class MacCertificate {
+    private final String certificate;
+    private final boolean verbose;
+
+    public MacCertificate(String certificate) {
+        this.certificate = certificate;
+        this.verbose = false;
+    }
+
+    public MacCertificate(String certificate, boolean verbose) {
+        this.certificate = certificate;
+        this.verbose = verbose;
+    }
+
+    public boolean isValid() {
+        return verifyCertificate(this.certificate, verbose);
+    }
+
+    private static File findCertificate(String certificate, boolean verbose) {
+        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, verbose, false, ps);
+
+            File output = File.createTempFile("tempfile", ".tmp");
+            PrintStream p = new PrintStream(
+                    new BufferedOutputStream(
+                            new FileOutputStream(output, true)));
+            BufferedReader bfReader = new BufferedReader(
+                    new InputStreamReader(
+                            new ByteArrayInputStream(baos.toByteArray())));
+            String line = null;
+
+            while((line = bfReader.readLine()) != null){
+                p.println(line);
+            }
+
+            p.close();
+            result = output;
+        }
+        catch (IOException ignored) {}
+
+        return result;
+    }
+
+    private static Date findCertificateDate(String filename, boolean verbose) {
+        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, verbose, 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 ioe) {
+        }
+        catch (ParseException ex) {
+        }
+
+        return result;
+    }
+
+    private static boolean verifyCertificate(
+            String certificate, boolean verbose) {
+        boolean result = false;
+
+        try {
+            File file = null;
+            Date certificateDate = null;
+
+            try {
+                file = findCertificate(certificate, verbose);
+
+                if (file != null) {
+                    certificateDate = findCertificateDate(
+                            file.getCanonicalPath(), verbose);
+                }
+            }
+            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.packager/macosx/classes/jdk/packager/internal/mac/MacDmgBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.mac;
+
+import jdk.packager.internal.*;
+import jdk.packager.internal.IOUtils;
+import jdk.packager.internal.resources.mac.MacResources;
+
+import java.io.*;
+import java.text.MessageFormat;
+import java.util.*;
+import jdk.packager.internal.Arguments;
+
+import static jdk.packager.internal.StandardBundlerParam.*;
+
+
+public class MacDmgBundler extends MacBaseInstallerBundler {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.mac.MacDmgBundler");
+
+    static final String DEFAULT_BACKGROUND_IMAGE="background_dmg.png";
+    static final String DEFAULT_DMG_SETUP_SCRIPT="DMGsetup.scpt";
+    static final String TEMPLATE_BUNDLE_ICON = "GenericApp.icns";
+
+    static final String DEFAULT_LICENSE_PLIST="lic_template.plist";
+
+    public static final BundlerParamInfo<String> INSTALLER_SUFFIX =
+            new StandardBundlerParam<> (
+            I18N.getString("param.installer-suffix.name"),
+            I18N.getString("param.installer-suffix.description"),
+            "mac.dmg.installerName.suffix",
+            String.class,
+            params -> "",
+            (s, p) -> s);
+
+    public MacDmgBundler() {
+        super();
+        baseResourceLoader = MacResources.class;
+    }
+
+    //@Override
+    public File bundle(Map<String, ? super Object> params, File outdir) {
+        Log.info(MessageFormat.format(I18N.getString("message.building-dmg"),
+                APP_NAME.fetchFrom(params)));
+        if (!outdir.isDirectory() && !outdir.mkdirs()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-create-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+        if (!outdir.canWrite()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-write-to-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+
+        File appImageDir = APP_IMAGE_BUILD_ROOT.fetchFrom(params);
+        try {
+            appImageDir.mkdirs();
+
+            if (prepareAppBundle(params, true) != null &&
+                    prepareConfigFiles(params)) {
+                File configScript = getConfig_Script(params);
+                if (configScript.exists()) {
+                    Log.info(MessageFormat.format(
+                            I18N.getString("message.running-script"),
+                            configScript.getAbsolutePath()));
+                    IOUtils.run("bash", configScript,
+                            ECHO_MODE.fetchFrom(params));
+                }
+
+                return buildDMG(params, outdir);
+            }
+            return null;
+        } catch (IOException ex) {
+            Log.verbose(ex);
+            return null;
+        } finally {
+            try {
+                if (appImageDir != null &&
+                        PREDEFINED_APP_IMAGE.fetchFrom(params) == null &&
+                        (PREDEFINED_RUNTIME_IMAGE.fetchFrom(params) == null ||
+                        !Arguments.CREATE_JRE_INSTALLER.fetchFrom(params)) &&
+                        !Log.isDebug()) {
+                    IOUtils.deleteRecursive(appImageDir);
+                } else if (appImageDir != null) {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "message.intermediate-image-location"),
+                            appImageDir.getAbsolutePath()));
+                }
+                if (!ECHO_MODE.fetchFrom(params)) {
+                    //cleanup
+                    cleanupConfigFiles(params);
+                } else {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "message.config-save-location"),
+                            CONFIG_ROOT.fetchFrom(params).getAbsolutePath()));
+                }
+            } catch (IOException ex) {
+                Log.debug(ex);
+                //noinspection ReturnInsideFinallyBlock
+                return null;
+            }
+        }
+    }
+
+    //remove
+    protected void cleanupConfigFiles(Map<String, ? super Object> params) {
+        if(!StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            if (getConfig_VolumeBackground(params) != null) {
+                getConfig_VolumeBackground(params).delete();
+            }
+            if (getConfig_VolumeIcon(params) != null) {
+                getConfig_VolumeIcon(params).delete();
+            }
+            if (getConfig_VolumeScript(params) != null) {
+                getConfig_VolumeScript(params).delete();
+            }
+            if (getConfig_Script(params) != null) {
+                getConfig_Script(params).delete();
+            }
+            if (getConfig_LicenseFile(params) != null) {
+                getConfig_LicenseFile(params).delete();
+            }
+            APP_BUNDLER.fetchFrom(params).cleanupConfigFiles(params);
+        }
+    }
+
+    private static final String hdiutil = "/usr/bin/hdiutil";
+
+    private void prepareDMGSetupScript(String volumeName,
+            Map<String, ? super Object> p) throws IOException {
+        File dmgSetup = getConfig_VolumeScript(p);
+        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(p));
+
+        data.put("DEPLOY_INSTALL_LOCATION", "(path to desktop folder)");
+        data.put("DEPLOY_INSTALL_NAME", "Desktop");
+
+        Writer w = new BufferedWriter(new FileWriter(dmgSetup));
+        w.write(preprocessTextResource(
+                MacAppBundler.MAC_BUNDLER_PREFIX + dmgSetup.getName(),
+                I18N.getString("resource.dmg-setup-script"),
+                        DEFAULT_DMG_SETUP_SCRIPT, data, VERBOSE.fetchFrom(p),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(p)));
+        w.close();
+    }
+
+    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 {
+            File licFile = null;
+
+            List<String> licFiles = LICENSE_FILE.fetchFrom(params);
+            if (licFiles.isEmpty()) {
+                return;
+            }
+            String licFileStr = licFiles.get(0);
+
+            for (RelativeFileSet rfs : APP_RESOURCES_LIST.fetchFrom(params)) {
+                if (rfs.contains(licFileStr)) {
+                    licFile = new File(rfs.getBaseDirectory(), licFileStr);
+                    break;
+                }
+            }
+
+            if (licFile == null) {
+                // this is NPE protection,
+                // validate should have caught it's absence
+                // so we don't complain or throw an error
+                return;
+            }
+
+            byte[] licenseContentOriginal = IOUtils.readFully(licFile);
+            String licenseInBase64 =
+                    Base64.getEncoder().encodeToString(licenseContentOriginal);
+
+            Map<String, String> data = new HashMap<>();
+            data.put("APPLICATION_LICENSE_TEXT", licenseInBase64);
+
+            Writer w = new BufferedWriter(
+                    new FileWriter(getConfig_LicenseFile(params)));
+            w.write(preprocessTextResource(
+                    MacAppBundler.MAC_BUNDLER_PREFIX
+                    + getConfig_LicenseFile(params).getName(),
+                    I18N.getString("resource.license-setup"),
+                    DEFAULT_LICENSE_PLIST, data, VERBOSE.fetchFrom(params),
+                    DROP_IN_RESOURCES_ROOT.fetchFrom(params)));
+            w.close();
+
+        } catch (IOException ex) {
+            Log.verbose(ex);
+        }
+    }
+
+    private boolean prepareConfigFiles(Map<String, ? super Object> params)
+            throws IOException {
+        File bgTarget = getConfig_VolumeBackground(params);
+        fetchResource(MacAppBundler.MAC_BUNDLER_PREFIX + bgTarget.getName(),
+                I18N.getString("resource.dmg-background"),
+                DEFAULT_BACKGROUND_IMAGE,
+                bgTarget,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+
+        File iconTarget = getConfig_VolumeIcon(params);
+        if (MacAppBundler.ICON_ICNS.fetchFrom(params) == null ||
+                !MacAppBundler.ICON_ICNS.fetchFrom(params).exists()) {
+            fetchResource(
+                    MacAppBundler.MAC_BUNDLER_PREFIX + iconTarget.getName(),
+                    I18N.getString("resource.volume-icon"),
+                    TEMPLATE_BUNDLE_ICON,
+                    iconTarget,
+                    VERBOSE.fetchFrom(params),
+                    DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        } else {
+            fetchResource(
+                    MacAppBundler.MAC_BUNDLER_PREFIX + iconTarget.getName(),
+                    I18N.getString("resource.volume-icon"),
+                    MacAppBundler.ICON_ICNS.fetchFrom(params),
+                    iconTarget,
+                    VERBOSE.fetchFrom(params),
+                    DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        }
+
+
+        fetchResource(MacAppBundler.MAC_BUNDLER_PREFIX
+                + getConfig_Script(params).getName(),
+                I18N.getString("resource.post-install-script"),
+                (String) null,
+                getConfig_Script(params),
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(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" namr 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"};
+
+        for (String path: typicalPaths) {
+            File f = new File(path);
+            if (f.exists() && f.canExecute()) {
+                return path;
+            }
+        }
+
+        //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> p, File outdir)
+            throws IOException {
+        File imagesRoot = IMAGES_ROOT.fetchFrom(p);
+        if (!imagesRoot.exists()) imagesRoot.mkdirs();
+
+        File protoDMG = new File(imagesRoot, APP_NAME.fetchFrom(p) +"-tmp.dmg");
+        File finalDMG = new File(outdir, INSTALLER_NAME.fetchFrom(p)
+                + INSTALLER_SUFFIX.fetchFrom(p)
+                + ".dmg");
+
+        File srcFolder = APP_IMAGE_BUILD_ROOT.fetchFrom(p);
+        File predefinedImage = StandardBundlerParam.getPredefinedAppImage(p);
+        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 = Log.isDebug() ? "-verbose" : "-quiet";
+
+        //create temp image
+        ProcessBuilder pb = new ProcessBuilder(
+                hdiutil,
+                "create",
+                hdiUtilVerbosityFlag,
+                "-srcfolder", srcFolder.getAbsolutePath(),
+                "-volname", APP_NAME.fetchFrom(p),
+                "-ov", protoDMG.getAbsolutePath(),
+                "-fs", "HFS+",
+                "-format", "UDRW");
+        IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+
+        //mount temp image
+        pb = new ProcessBuilder(
+                hdiutil,
+                "attach",
+                protoDMG.getAbsolutePath(),
+                hdiUtilVerbosityFlag,
+                "-mountroot", imagesRoot.getAbsolutePath());
+        IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+
+        File mountedRoot =
+                new File(imagesRoot.getAbsolutePath(), APP_NAME.fetchFrom(p));
+
+        //volume icon
+        File volumeIconFile = new File(mountedRoot, ".VolumeIcon.icns");
+        IOUtils.copyFile(getConfig_VolumeIcon(p),
+                volumeIconFile);
+
+        pb = new ProcessBuilder("osascript",
+                getConfig_VolumeScript(p).getAbsolutePath());
+        IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+
+        // 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
+                // http://endrift.com/blog/2010/06/14/dmg-files-volume-icons-cli
+                // (might not work on Mac 10.13 with old XCode)
+                pb = new ProcessBuilder(
+                        setFileUtility,
+                        "-c", "icnC",
+                        volumeIconFile.getAbsolutePath());
+                IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+                volumeIconFile.setReadOnly();
+
+                pb = new ProcessBuilder(
+                        setFileUtility,
+                        "-a", "C",
+                        mountedRoot.getAbsolutePath());
+                IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+            } catch (IOException ex) {
+                Log.info(ex.getMessage());
+                Log.verbose(
+                    "Cannot enable custom icon using SetFile utility");
+            }
+        } else {
+            Log.verbose(
+                "Skip enabling custom icon as SetFile utility is not found");
+        }
+
+        // Detach the temporary image
+        pb = new ProcessBuilder(
+                hdiutil,
+                "detach",
+                hdiUtilVerbosityFlag,
+                mountedRoot.getAbsolutePath());
+        IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+
+        // Compress it to a new image
+        pb = new ProcessBuilder(
+                hdiutil,
+                "convert",
+                protoDMG.getAbsolutePath(),
+                hdiUtilVerbosityFlag,
+                "-format", "UDZO",
+                "-o", finalDMG.getAbsolutePath());
+        IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+
+        //add license if needed
+        if (getConfig_LicenseFile(p).exists()) {
+            //hdiutil unflatten your_image_file.dmg
+            pb = new ProcessBuilder(
+                    hdiutil,
+                    "unflatten",
+                    finalDMG.getAbsolutePath()
+            );
+            IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+
+            //add license
+            pb = new ProcessBuilder(
+                    hdiutil,
+                    "udifrez",
+                    finalDMG.getAbsolutePath(),
+                    "-xml",
+                    getConfig_LicenseFile(p).getAbsolutePath()
+            );
+            IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+
+            //hdiutil flatten your_image_file.dmg
+            pb = new ProcessBuilder(
+                    hdiutil,
+                    "flatten",
+                    finalDMG.getAbsolutePath()
+            );
+            IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+
+        }
+
+        //Delete the temporary image
+        protoDMG.delete();
+
+        Log.info(MessageFormat.format(I18N.getString(
+                "message.output-to-location"),
+                APP_NAME.fetchFrom(p), finalDMG.getAbsolutePath()));
+
+        return finalDMG;
+    }
+
+
+    //////////////////////////////////////////////////////////////////////////
+    // Implement Bundler
+    //////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String getName() {
+        return I18N.getString("bundler.name");
+    }
+
+    @Override
+    public String getDescription() {
+        return I18N.getString("bundler.description");
+    }
+
+    @Override
+    public String getID() {
+        return "dmg";
+    }
+
+    @Override
+    public Collection<BundlerParamInfo<?>> getBundleParameters() {
+        Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
+        results.addAll(MacAppBundler.getAppBundleParameters());
+        results.addAll(getDMGBundleParameters());
+        return results;
+    }
+
+    public Collection<BundlerParamInfo<?>> getDMGBundleParameters() {
+        Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
+
+        results.addAll(MacAppBundler.getAppBundleParameters());
+        results.addAll(Arrays.asList(
+                INSTALLER_SUFFIX,
+                LICENSE_FILE
+        ));
+
+        return results;
+    }
+
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws UnsupportedPlatformException, ConfigException {
+        try {
+            if (params == null) throw new ConfigException(
+                    I18N.getString("error.parameters-null"),
+                    I18N.getString("error.parameters-null.advice"));
+
+            //run basic validation to ensure requirements are met
+            //we are not interested in return code, only possible exception
+            validateAppImageAndBundeler(params);
+
+            // validate license file, if used, exists in the proper place
+            if (params.containsKey(LICENSE_FILE.getID())) {
+                List<RelativeFileSet> appResourcesList =
+                    APP_RESOURCES_LIST.fetchFrom(params);
+                for (String license : LICENSE_FILE.fetchFrom(params)) {
+                    boolean found = false;
+                    for (RelativeFileSet appResources : appResourcesList) {
+                        found = found || appResources.contains(license);
+                    }
+                    if (!found) {
+                        throw new ConfigException(
+                                I18N.getString("error.license-missing"),
+                                MessageFormat.format(I18N.getString(
+                                "error.license-missing.advice"), license));
+                    }
+                }
+            }
+
+            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) {
+        return bundle(params, outputParentDir);
+    }
+    
+    @Override    
+    public boolean supported() {
+        return Platform.getPlatform() == Platform.MAC;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/mac/MacPkgBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,627 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal.mac;
+
+import jdk.packager.internal.BundlerParamInfo;
+import jdk.packager.internal.StandardBundlerParam;
+import jdk.packager.internal.Log;
+import jdk.packager.internal.ConfigException;
+import jdk.packager.internal.IOUtils;
+import jdk.packager.internal.Platform;
+import jdk.packager.internal.RelativeFileSet;
+import jdk.packager.internal.UnsupportedPlatformException;
+import jdk.packager.internal.resources.mac.MacResources;
+import jdk.packager.internal.builders.mac.MacAppImageBuilder;
+import jdk.packager.internal.Arguments;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.Writer;
+import java.net.URLEncoder;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ResourceBundle;
+
+import static jdk.packager.internal.StandardBundlerParam.*;
+import static
+        jdk.packager.internal.mac.MacBaseInstallerBundler.SIGNING_KEYCHAIN;
+import static
+        jdk.packager.internal.mac.MacBaseInstallerBundler.SIGNING_KEY_USER;
+
+public class MacPkgBundler extends MacBaseInstallerBundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.mac.MacPkgBundler");
+
+    public final static String MAC_BUNDLER_PREFIX =
+            BUNDLER_PREFIX + "macosx" + File.separator;
+
+    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<>(
+            I18N.getString("param.packages-root.name"),
+            I18N.getString("param.packages-root.description"),
+            "mac.pkg.packagesRoot",
+            File.class,
+            params -> {
+                File packagesRoot =
+                        new File(BUILD_ROOT.fetchFrom(params), "packages");
+                packagesRoot.mkdirs();
+                return packagesRoot;
+            },
+            (s, p) -> new File(s));
+
+
+    protected final BundlerParamInfo<File> SCRIPTS_DIR =
+            new StandardBundlerParam<>(
+            I18N.getString("param.scripts-dir.name"),
+            I18N.getString("param.scripts-dir.description"),
+            "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<>(
+            I18N.getString("param.signing-key-developer-id-installer.name"),
+            I18N.getString(
+            "param.signing-key-developer-id-installer.description"),
+            "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, VERBOSE.fetchFrom(params));
+
+                        if (!certificate.isValid()) {
+                            Log.info(MessageFormat.format(
+                                    I18N.getString("error.certificate.expired"),
+                                    result));
+                        }
+                    }
+
+                    return result;
+                },
+            (s, p) -> s);
+    
+    public static final BundlerParamInfo<String> MAC_INSTALL_DIR =
+            new StandardBundlerParam<>(
+            I18N.getString("param.mac-install-dir.name"),
+            I18N.getString("param.mac-install-dir.description"),
+            "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<> (
+            I18N.getString("param.installer-suffix.name"),
+            I18N.getString("param.installer-suffix.description"),
+            "mac.pkg.installerName.suffix",
+            String.class,
+            params -> "",
+            (s, p) -> s);
+
+    public MacPkgBundler() {
+        super();
+        baseResourceLoader = MacResources.class;
+    }
+
+    // @Override
+    public File bundle(Map<String, ? super Object> params, File outdir) {
+        Log.info(MessageFormat.format(I18N.getString("message.building-pkg"),
+                APP_NAME.fetchFrom(params)));
+        if (!outdir.isDirectory() && !outdir.mkdirs()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-create-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+        if (!outdir.canWrite()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-write-to-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+
+        File appImageDir = null;
+        try {
+            appImageDir = prepareAppBundle(params, false);
+
+            if (appImageDir != null && prepareConfigFiles(params)) {
+
+                File configScript = getConfig_Script(params);
+                if (configScript.exists()) {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "message.running-script"),
+                            configScript.getAbsolutePath()));
+                    IOUtils.run("bash", configScript,
+                            ECHO_MODE.fetchFrom(params));
+                }
+
+                return createPKG(params, outdir, appImageDir);
+            }
+            return null;
+        } catch (IOException ex) {
+            Log.verbose(ex);
+            return null;
+        } finally {
+            try {
+                if (appImageDir != null && 
+                        PREDEFINED_APP_IMAGE.fetchFrom(params) == null &&
+                        (PREDEFINED_RUNTIME_IMAGE.fetchFrom(params) == null ||
+                        !Arguments.CREATE_JRE_INSTALLER.fetchFrom(params)) && 
+                        !Log.isDebug()) {
+                    IOUtils.deleteRecursive(appImageDir);
+                } else if (appImageDir != null) {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "message.intermediate-image-location"),
+                            appImageDir.getAbsolutePath()));
+                }
+                if (!ECHO_MODE.fetchFrom(params)) {
+                    // cleanup
+                    cleanupConfigFiles(params);
+                } else {
+                    Log.info(MessageFormat.format(
+                            I18N.getString("message.config-save-location"),
+                            CONFIG_ROOT.fetchFrom(params).getAbsolutePath()));
+                }
+            } catch (IOException ex) {
+                Log.debug(ex);
+                // noinspection ReturnInsideFinallyBlock
+                return null;
+            }
+        }
+    }
+
+    private File getPackages_AppPackage(Map<String, ? super Object> params) {
+        return new File(PACKAGES_ROOT.fetchFrom(params),
+                APP_FS_NAME.fetchFrom(params) + "-app.pkg");
+    }
+
+    private File getPackages_DaemonPackage(Map<String, ? super Object> params) {
+        return new File(PACKAGES_ROOT.fetchFrom(params),
+                APP_FS_NAME.fetchFrom(params) + "-daemon.pkg");
+    }
+
+    private void cleanupPackagesFiles(Map<String, ? super Object> params) {
+        if(!StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            if (getPackages_AppPackage(params) != null) {
+                getPackages_AppPackage(params).delete();
+            }
+            if (getPackages_DaemonPackage(params) != null) {
+                getPackages_DaemonPackage(params).delete();
+            }
+        }
+    }
+
+    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 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 void cleanupPackageScripts(Map<String, ? super Object> params) {
+        if(!StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            if (getScripts_PreinstallFile(params) != null) {
+                getScripts_PreinstallFile(params).delete();
+            }
+            if (getScripts_PostinstallFile(params) != null) {
+                getScripts_PostinstallFile(params).delete();
+            }
+        }
+    }
+
+    private void cleanupConfigFiles(Map<String, ? super Object> params) {
+        if(!StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            if (getConfig_DistributionXMLFile(params) != null) {
+                getConfig_DistributionXMLFile(params).delete();
+            }
+            if (getConfig_BackgroundImage(params) != null) {
+                getConfig_BackgroundImage(params).delete();
+            }
+        }
+    }
+
+    private String getAppIdentifier(Map<String, ? super Object> params) {
+        return IDENTIFIER.fetchFrom(params);
+    }
+
+    private String getDaemonIdentifier(Map<String, ? super Object> params) {
+        return IDENTIFIER.fetchFrom(params) + ".daemon";
+    }
+
+    private void preparePackageScripts(Map<String, ? super Object> params) 
+            throws IOException {
+        Log.verbose(I18N.getString("message.preparing-scripts"));
+
+        Map<String, String> data = new HashMap<>();
+
+        data.put("DEPLOY_DAEMON_IDENTIFIER", getDaemonIdentifier(params));
+        data.put("DEPLOY_LAUNCHD_PLIST_FILE",
+                IDENTIFIER.fetchFrom(params).toLowerCase() + ".launchd.plist");
+
+        Writer w = new BufferedWriter(
+                new FileWriter(getScripts_PreinstallFile(params)));
+        String content = preprocessTextResource(MAC_BUNDLER_PREFIX
+                + getScripts_PreinstallFile(params).getName(),
+                I18N.getString("resource.pkg-preinstall-script"),
+                TEMPLATE_PREINSTALL_SCRIPT,
+                data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        w.write(content);
+        w.close();
+        getScripts_PreinstallFile(params).setExecutable(true, false);
+
+        w = new BufferedWriter(
+                new FileWriter(getScripts_PostinstallFile(params)));
+        content = preprocessTextResource(MAC_BUNDLER_PREFIX
+                + getScripts_PostinstallFile(params).getName(),
+                I18N.getString("resource.pkg-postinstall-script"),
+                TEMPLATE_POSTINSTALL_SCRIPT,
+                data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        w.write(content);
+        w.close();
+        getScripts_PostinstallFile(params).setExecutable(true, false);
+    }
+
+    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()));
+
+        PrintStream out = new PrintStream(f);
+
+        out.println(
+                "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>");
+        out.println("<installer-gui-script minSpecVersion=\"1\">");
+
+        out.println("<title>" + APP_NAME.fetchFrom(params) + "</title>");
+        out.println("<background" + " file=\""
+                + getConfig_BackgroundImage(params).getName()
+                + "\""
+                + " mime-type=\"image/png\""
+                + " alignment=\"bottomleft\" "
+                + " scaling=\"none\""
+                + "/>");
+
+        if (!LICENSE_FILE.fetchFrom(params).isEmpty()) {
+            File licFile = null;
+
+            List<String> licFiles = LICENSE_FILE.fetchFrom(params);
+            if (licFiles.isEmpty()) {
+                return;
+            }
+            String licFileStr = licFiles.get(0);
+
+            for (RelativeFileSet rfs : APP_RESOURCES_LIST.fetchFrom(params)) {
+                if (rfs.contains(licFileStr)) {
+                    licFile = new File(rfs.getBaseDirectory(), licFileStr);
+                    break;
+                }
+            }
+
+            // this is NPE protection, validate should have caught it's absence
+            // so we don't complain or throw an error
+            if (licFile != null) {
+                out.println("<license" +
+                        " file=\"" + licFile.getAbsolutePath() + "\"" +
+                        " mime-type=\"text/rtf\"" +
+                        "/>");
+            }
+        }
+
+        /*
+         * Note that the content of the distribution file
+         * below is generated by productbuild --synthesize
+         */
+
+        String appId = getAppIdentifier(params);
+        String daemonId = getDaemonIdentifier(params);
+
+        out.println("<pkg-ref id=\"" + appId + "\"/>");
+
+        out.println("<options customize=\"never\" require-scripts=\"false\"/>");
+        out.println("<choices-outline>");
+        out.println("    <line choice=\"default\">");
+        out.println("        <line choice=\"" + appId + "\"/>");
+        out.println("    </line>");
+        out.println("</choices-outline>");
+        out.println("<choice id=\"default\"/>");
+        out.println("<choice id=\"" + appId + "\" visible=\"false\">");
+        out.println("    <pkg-ref id=\"" + appId + "\"/>");
+        out.println("</choice>");
+        out.println("<pkg-ref id=\"" + appId + "\" version=\""
+                + VERSION.fetchFrom(params) + "\" onConclusion=\"none\">"
+                + URLEncoder.encode(getPackages_AppPackage(params).getName(),
+                "UTF-8") + "</pkg-ref>");
+
+        out.println("</installer-gui-script>");
+
+        out.close();
+    }
+
+    private boolean prepareConfigFiles(Map<String, ? super Object> params)
+            throws IOException {
+        File imageTarget = getConfig_BackgroundImage(params);
+        fetchResource(MacAppBundler.MAC_BUNDLER_PREFIX + imageTarget.getName(),
+                I18N.getString("resource.pkg-background-image"),
+                DEFAULT_BACKGROUND_IMAGE,
+                imageTarget,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+
+        prepareDistributionXMLFile(params);
+
+        fetchResource(MacAppBundler.MAC_BUNDLER_PREFIX
+                + getConfig_Script(params).getName(),
+                I18N.getString("resource.post-install-script"),
+                (String) null,
+                getConfig_Script(params),
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(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 File createPKG(Map<String, ? super Object> params,
+            File outdir, File appLocation) {
+        // generic find attempt
+        try {
+            File appPKG = getPackages_AppPackage(params);
+
+            // build application package
+            ProcessBuilder pb = new ProcessBuilder("pkgbuild",
+                    "--component",
+                    appLocation.toString(),
+                    "--install-location",
+                    MAC_INSTALL_DIR.fetchFrom(params),
+                    appPKG.getAbsolutePath());
+            IOUtils.exec(pb, ECHO_MODE.fetchFrom(params));
+
+            // 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.info(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, ECHO_MODE.fetchFrom(params));
+
+            return finalPKG;
+        } catch (Exception ignored) {
+            Log.verbose(ignored);
+            return null;
+        } finally {
+            if (!ECHO_MODE.fetchFrom(params)) {
+                cleanupPackagesFiles(params);
+                cleanupConfigFiles(params);
+            }
+        }
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+    // Implement Bundler
+    //////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public String getName() {
+        return I18N.getString("bundler.name");
+    }
+
+    @Override
+    public String getDescription() {
+        return I18N.getString("bundler.description");
+    }
+
+    @Override
+    public String getID() {
+        return "pkg";
+    }
+
+    @Override
+    public Collection<BundlerParamInfo<?>> getBundleParameters() {
+        Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
+        results.addAll(MacAppBundler.getAppBundleParameters());
+        results.addAll(getPKGBundleParameters());
+        return results;
+    }
+
+    public Collection<BundlerParamInfo<?>> getPKGBundleParameters() {
+        Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
+
+        results.addAll(MacAppBundler.getAppBundleParameters());
+        results.addAll(Arrays.asList(
+                DEVELOPER_ID_INSTALLER_SIGNING_KEY,
+                // IDENTIFIER,
+                INSTALLER_SUFFIX,
+                LICENSE_FILE,
+                // SERVICE_HINT,
+                SIGNING_KEYCHAIN));
+
+        return results;
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws UnsupportedPlatformException, ConfigException {
+        try {
+            if (params == null) throw new ConfigException(
+                    I18N.getString("error.parameters-null"),
+                    I18N.getString("error.parameters-null.advice"));
+
+            // run basic validation to ensure requirements are met
+            // we are not interested in return code, only possible exception
+            validateAppImageAndBundeler(params);
+
+            // validate license file, if used, exists in the proper place
+            if (params.containsKey(LICENSE_FILE.getID())) {
+                List<RelativeFileSet> appResourcesList =
+                        APP_RESOURCES_LIST.fetchFrom(params);
+                for (String license : LICENSE_FILE.fetchFrom(params)) {
+                    boolean found = false;
+                    for (RelativeFileSet appResources : appResourcesList) {
+                        found = found || appResources.contains(license);
+                    }
+                    if (!found) {
+                        throw new ConfigException(
+                                I18N.getString("error.license-missing"),
+                                MessageFormat.format(
+                                I18N.getString("error.license-missing.advice"),
+                                license));
+                    }
+                }
+            }
+
+            // 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) {
+        return bundle(params, outputParentDir);
+    }
+    
+    @Override    
+    public boolean supported() {
+        return Platform.getPlatform() == Platform.MAC;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/builders/mac/MacAppImageBuilder.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,77 @@
+bundler.name=Mac Application Image
+bundler.description=A Directory based image of a mac Application with an optionally co-bundled JRE.  Used as a base for the Installer bundlers
+
+param.signing-key-developer-id-app.name=Apple Developer ID Application Signing Key
+param.signing-key-developer-id-app.description=The full name of the Apple Developer ID Application signing key.
+
+param.icon-icns.name=.icns Icon
+param.icon-icns.description= Icon for the application, in ICNS format.
+
+param.config-root.name=
+param.config-root.description=
+
+param.configure-launcher-in-plist=Configure Launcher in Info.plist
+param.configure-launcher-in-plist.description=Should the legacy method of configuring hte launcher in the Info.plist be used.
+
+param.category-name=Category
+param.category-name.description=Mac App Store Categories. Note that the key is the string to display to the user and the value is the id of the category.
+
+param.cfbundle-name.name=CFBundleName
+param.cfbundle-name.description=The name of the app as it appears in the Menu Bar.  This can be different from the application name.  This name should be less than 16 characters long and be suitable for displaying in the menu bar and the app's Info window.
+
+param.cfbundle-identifier.name=CFBundleIdentifier
+param.cfbundle-identifier.description=An identifier that uniquely identifies the application for MacOSX (and on the Mac App Store).  May only use alphanumeric (A-Z,a-z,0-9), hyphen (-), and period (.) characters.
+
+param.cfbundle-version.name=CFBundleVersion
+param.cfbundle-version.description=An computer readable version for the CFBundle.  May contain only digits and from zero to two dots, such as "1.8.1" or "100".
+
+param.bundle-id-signing-prefix.name=Bundle Signing Prefix
+param.bundle-id-signing-prefix.description=When signing the application bundle this value is prefixed to all components that need to be signed that don't have an existing CFBundleIdentifier.
+
+param.raw-executable-url.name=Launcher URL
+param.raw-executable-url.description=Override the packager default launcher with a custom launcher.
+
+param.default-icon-icns=Default Icon
+param.default-icon-icns.description=The Default Icon for when a user does not specify an icns file.
+
+param.runtime.name=JRE
+param.runtime.description=The Java Runtime to co-bundle.  The default value is the current JRE running the bundler.  A value of null will cause no JRE to be co-bundled and the system JRE will be used to launch the application.
+
+param.sign-bundle.name=Sign Bundle
+param.sign-bundle.description=Request that the bundle be signed.
+
+param.images-root.name=
+param.images-root.description=
+
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+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.non-existent-runtime=The file for the Runtime/JRE directory does not exist.
+error.non-existent-runtime.advice=Point the runtime parameter to a directory that containes the JRE.
+error.cannot-detect-runtime-in-directory=Cannot determine which JRE/JDK exists in the specified runtime directory.
+error.cannot-detect-runtime-in-directory.advice=Point the runtime directory to one of the JDK/JRE root, the Contents/Home directory of that root, or the Contents/Home/jre directory of the JDK.
+resource.app-info-plist=Application Info.plist
+resource.runtime-info-plist=Java Runtime Info.plist
+
+message.config-save-location=Config files are saved to {0}. Use them to customize package.
+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.no-mac-jre-support=Currently Macs require a JDK to package
+message.creating-app-bundle=Creating app bundle\: {0}
+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.using-default-resource=Using default package resource {0} (add {1} to the class path to customize)
+message.using-custom-resource-from-file=Using custom package resource {0} (loaded from file {1})
+message.using-custom-resource-from-classpath=Using custom package resource {0} (loaded from {1})
+message.using-default-resource-from-classpath=Using default package resource {0} (add {1} to the class path to customize)
+message.ignoring.symlink=Warning: codesign is skipping the symlink {0}
+message.keychain.error=Error: unable to get keychain list.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/builders/mac/MacAppImageBuilder_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,73 @@
+bundler.name=Mac\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8
+bundler.description=\u30AA\u30D7\u30B7\u30E7\u30F3\u3067JRE\u304C\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u3066\u3044\u308BMac\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FB\u30D9\u30FC\u30B9\u306E\u30A4\u30E1\u30FC\u30B8\u3002\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FB\u30D0\u30F3\u30C9\u30EB\u306E\u30D9\u30FC\u30B9\u3068\u3057\u3066\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+
+param.signing-key-developer-id-app.name=Apple Developer ID\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u7F72\u540D\u30AD\u30FC
+param.signing-key-developer-id-app.description=Apple Developer ID\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u7F72\u540D\u30AD\u30FC\u306E\u30D5\u30EB\u30FB\u30CD\u30FC\u30E0\u3002
+
+param.icon-icns.name=.icns\u30A2\u30A4\u30B3\u30F3
+param.icon-icns.description= ICNS\u5F62\u5F0F\u3067\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30A2\u30A4\u30B3\u30F3\u3002
+
+param.config-root.name=
+param.config-root.description=
+
+param.configure-launcher-in-plist=Info.plist\u3067\u306E\u30E9\u30F3\u30C1\u30E3\u306E\u69CB\u6210
+param.configure-launcher-in-plist.description=Info.plist\u3067\u306E\u30E9\u30F3\u30C1\u30E3\u306E\u69CB\u6210\u306B\u306F\u30EC\u30AC\u30B7\u30FC\u30FB\u30E1\u30BD\u30C3\u30C9\u3092\u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
+
+param.category-name=\u30AB\u30C6\u30B4\u30EA
+param.category-name.description=Mac App Store\u306E\u30AB\u30C6\u30B4\u30EA\u3002\u30AD\u30FC\u306F\u30E6\u30FC\u30B6\u30FC\u306B\u8868\u793A\u3055\u308C\u308B\u6587\u5B57\u5217\u3067\u3001\u5024\u306F\u30AB\u30C6\u30B4\u30EA\u306EID\u3067\u3059\u3002
+
+param.cfbundle-name.name=CFBundleName
+param.cfbundle-name.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u304C\u30E1\u30CB\u30E5\u30FC\u30FB\u30D0\u30FC\u306B\u8868\u793A\u3055\u308C\u308B\u969B\u306E\u540D\u524D\u3002\u3053\u308C\u306F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D\u3068\u306F\u7570\u306A\u308B\u5834\u5408\u304C\u3042\u308A\u307E\u3059\u3002\u3053\u306E\u540D\u524D\u306F16\u6587\u5B57\u672A\u6E80\u3068\u3057\u3001\u30E1\u30CB\u30E5\u30FC\u30FB\u30D0\u30FC\u3068\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u60C5\u5831\u30A6\u30A3\u30F3\u30C9\u30A6\u3067\u306E\u8868\u793A\u306B\u9069\u3057\u305F\u3082\u306E\u306B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
+
+param.cfbundle-identifier.name=CFBundleIdentifier
+param.cfbundle-identifier.description=MacOSX(\u304A\u3088\u3073Mac App Store)\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u4E00\u610F\u306B\u8B58\u5225\u3059\u308B\u8B58\u5225\u5B50\u3002\u82F1\u6570\u5B57(A-Z\u3001a-z\u30010-9)\u3001\u30CF\u30A4\u30D5\u30F3(-)\u304A\u3088\u3073\u30D4\u30EA\u30AA\u30C9(.)\u306E\u307F\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002
+
+param.cfbundle-version.name=CFBundleVersion
+param.cfbundle-version.description=\u30B3\u30F3\u30D4\u30E5\u30FC\u30BF\u3067\u8AAD\u53D6\u308A\u53EF\u80FD\u306ACFBundle\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3002\u6570\u5B57\u304A\u3088\u3073\u30BC\u30ED\u304B\u30892\u3064\u307E\u3067\u306E\u30C9\u30C3\u30C8\u306E\u307F\u3092\u542B\u3081\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059("1.8.1"\u3001"100"\u306A\u3069)\u3002
+
+param.bundle-id-signing-prefix.name=\u30D0\u30F3\u30C9\u30EB\u7F72\u540D\u63A5\u982D\u8F9E
+param.bundle-id-signing-prefix.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB\u306B\u7F72\u540D\u3059\u308B\u969B\u3001\u7F72\u540D\u3059\u308B\u5FC5\u8981\u306E\u3042\u308B\u3001\u65E2\u5B58\u306ECFBundleIdentifier\u3092\u6301\u305F\u306A\u3044\u3059\u3079\u3066\u306E\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u306B\u3053\u306E\u5024\u304C\u63A5\u982D\u8F9E\u3068\u3057\u3066\u4ED8\u3051\u3089\u308C\u307E\u3059\u3002
+
+param.raw-executable-url.name=\u30E9\u30F3\u30C1\u30E3URL
+param.raw-executable-url.description=\u30D1\u30C3\u30B1\u30FC\u30B8\u30E3\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30E9\u30F3\u30C1\u30E3\u3092\u30AB\u30B9\u30BF\u30E0\u30FB\u30E9\u30F3\u30C1\u30E3\u3067\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u3059\u3002
+
+param.default-icon-icns=\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3
+param.default-icon-icns.description=\u30E6\u30FC\u30B6\u30FC\u304C\u30A2\u30A4\u30B3\u30F3\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u306A\u3044\u5834\u5408\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3\u3002
+
+param.runtime.name=JRE
+param.runtime.description=\u30D0\u30F3\u30C9\u30EB\u3059\u308BJava\u30E9\u30F3\u30BF\u30A4\u30E0\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u306F\u3001\u30D0\u30F3\u30C9\u30E9\u3092\u5B9F\u884C\u3057\u3066\u3044\u308B\u73FE\u5728\u306EJRE\u3067\u3059\u3002\u5024\u304Cnull\u306E\u5834\u5408\u3001JRE\u306F\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305A\u3001\u30B7\u30B9\u30C6\u30E0\u306EJRE\u304C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u8D77\u52D5\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+
+param.images-root.name=
+param.images-root.description=
+
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+error.invalid-cfbundle-version=CFBundleVersion - ''{0}''\u304C\u7121\u52B9\u3067\u3059
+error.invalid-cfbundle-version.advice=\u4E92\u63DB\u6027\u306E\u3042\u308B'appVersion'\u3092\u8A2D\u5B9A\u3059\u308B\u304B\u3001'mac.CFBundleVersion'\u3092\u8A2D\u5B9A\u3057\u307E\u3059\u3002\u6709\u52B9\u306A\u30D0\u30FC\u30B8\u30E7\u30F3\u306F\u3001\u30C9\u30C3\u30C8\u3067\u533A\u5207\u3089\u308C\u305F1\u304B\u30893\u3064\u306E\u6574\u6570\u3067\u3059\u3002
+error.explicit-sign-no-cert=\u7F72\u540D\u304C\u660E\u793A\u7684\u306B\u8981\u6C42\u3055\u308C\u307E\u3057\u305F\u304C\u3001\u7F72\u540D\u8A3C\u660E\u66F8\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002
+error.explicit-sign-no-cert.advice=\u6709\u52B9\u306A\u8A3C\u660E\u66F8\u3092'mac.signing-key-developer-id-app'\u3067\u6307\u5B9A\u3059\u308B\u304B\u3001'signBundle'\u3092\u8A2D\u5B9A\u89E3\u9664\u3059\u308B\u304B\u3001\u307E\u305F\u306F'signBundle'\u3092false\u306B\u8A2D\u5B9A\u3057\u307E\u3059\u3002
+error.non-existent-runtime=\u30E9\u30F3\u30BF\u30A4\u30E0/JRE\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u30D5\u30A1\u30A4\u30EB\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002
+error.non-existent-runtime.advice=\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3001JRE\u3092\u542B\u3080\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002
+error.cannot-detect-runtime-in-directory=\u6307\u5B9A\u3057\u305F\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u3069\u306EJRE/JDK\u304C\u5B58\u5728\u3059\u308B\u306E\u304B\u3092\u7279\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-detect-runtime-in-directory.advice=\u30E9\u30A4\u30BF\u30A4\u30E0\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u3001JDK/JRE\u30EB\u30FC\u30C8\u3001\u305D\u306E\u30EB\u30FC\u30C8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4/\u30DB\u30FC\u30E0\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3001\u307E\u305F\u306FJDK\u306E\u30B3\u30F3\u30C6\u30F3\u30C4/\u30DB\u30FC\u30E0/jre\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002
+resource.app-info-plist=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306EInfo.plist
+resource.runtime-info-plist=Java\u30E9\u30F3\u30BF\u30A4\u30E0\u306EInfo.plist
+
+message.config-save-location=\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C{0}\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B\u306B\u306F\u3053\u308C\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+message.bundle-name-too-long-warning={0}\u304C16\u6587\u5B57\u3092\u8D85\u3048\u308B''{1}''\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059\u3002Mac\u3067\u306E\u64CD\u4F5C\u6027\u3092\u3088\u308A\u826F\u304F\u3059\u308B\u305F\u3081\u306B\u77ED\u304F\u3059\u308B\u3053\u3068\u3092\u691C\u8A0E\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+message.no-mac-jre-support=\u73FE\u5728\u3001Mac\u3067\u306FJDK\u3092\u30D1\u30C3\u30B1\u30FC\u30B8\u5316\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
+message.creating-app-bundle=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059: {0}
+message.null-classpath=Null\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30EA\u30BD\u30FC\u30B9\u3067\u3059\u304B\u3002
+message.preparing-info-plist=Info.plist\u3092\u6E96\u5099\u3057\u3066\u3044\u307E\u3059: {0}
+message.icon-not-icns= \u6307\u5B9A\u3057\u305F\u30A2\u30A4\u30B3\u30F3"{0}"\u306FICNS\u30D5\u30A1\u30A4\u30EB\u3067\u306F\u306A\u304F\u3001\u4F7F\u7528\u3055\u308C\u307E\u305B\u3093\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3\u304C\u305D\u306E\u4F4D\u7F6E\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+message.version-string-too-many-components=\u30D0\u30FC\u30B8\u30E7\u30F3\u6587\u5B57\u5217\u306B\u306F\u30011\u30011.2\u30011.2.3\u306A\u30691\u304B\u30893\u306E\u6570\u5B57\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002
+message.version-string-first-number-not-zero=CFBundleVersion\u306E\u6700\u521D\u306E\u6570\u5B57\u306F\u3001\u30BC\u30ED\u307E\u305F\u306F\u8CA0\u306E\u5024\u306B\u3067\u304D\u307E\u305B\u3093\u3002
+message.version-string-no-negative-numbers=\u30D0\u30FC\u30B8\u30E7\u30F3\u6587\u5B57\u5217\u306B\u8CA0\u306E\u6570\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093\u3002
+message.version-string-numbers-only=\u30D0\u30FC\u30B8\u30E7\u30F3\u6587\u5B57\u5217\u306F\u3001\u6570\u5B57\u30682\u3064\u307E\u3067\u306E\u30C9\u30C3\u30C8\u3067\u306E\u307F\u69CB\u6210\u3067\u304D\u307E\u3059\u3002
+message.creating-association-with-null-extension=null\u62E1\u5F35\u5B50\u3068\u306E\u95A2\u9023\u4ED8\u3051\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059\u3002
+
+message.using-default-resource=\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528({1}\u3092\u30AF\u30E9\u30B9\u30FB\u30D1\u30B9\u306B\u8FFD\u52A0\u3057\u3066\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA)
+message.using-custom-resource-from-file=\u30AB\u30B9\u30BF\u30E0\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528(\u30D5\u30A1\u30A4\u30EB{1}\u304B\u3089\u30ED\u30FC\u30C9\u6E08)
+message.using-custom-resource-from-classpath=\u30AB\u30B9\u30BF\u30E0\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528({1}\u304B\u3089\u30ED\u30FC\u30C9\u6E08)
+message.using-default-resource-from-classpath=\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528({1}\u3092\u30AF\u30E9\u30B9\u30FB\u30D1\u30B9\u306B\u8FFD\u52A0\u3057\u3066\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA)
+message.ignoring.symlink=\u8B66\u544A: codesign\u304Csymlink {0}\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u3066\u3044\u307E\u3059
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/builders/mac/MacAppImageBuilder_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,73 @@
+bundler.name=Mac \u5E94\u7528\u7A0B\u5E8F\u6620\u50CF
+bundler.description=\u4E00\u4E2A\u57FA\u4E8E\u76EE\u5F55\u7684 mac \u5E94\u7528\u7A0B\u5E8F\u6620\u50CF, \u53EF\u4EE5\u9009\u62E9\u6027\u5730\u5E26\u6709\u5171\u540C\u6253\u5305\u7684 JRE\u3002\u7528\u4F5C\u5B89\u88C5\u7A0B\u5E8F\u6253\u5305\u7A0B\u5E8F\u7684\u57FA\u7840
+
+param.signing-key-developer-id-app.name=Apple \u5F00\u53D1\u8005 ID \u5E94\u7528\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5
+param.signing-key-developer-id-app.description=Apple \u5F00\u53D1\u8005 ID \u5E94\u7528\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5\u7684\u5168\u540D\u3002
+
+param.icon-icns.name=.icns \u56FE\u6807
+param.icon-icns.description= \u5E94\u7528\u7A0B\u5E8F\u7684\u56FE\u6807, \u91C7\u7528 ICNS \u683C\u5F0F\u3002
+
+param.config-root.name=
+param.config-root.description=
+
+param.configure-launcher-in-plist=\u5728 Info.plist \u4E2D\u914D\u7F6E\u542F\u52A8\u7A0B\u5E8F
+param.configure-launcher-in-plist.description=\u662F\u5426\u5E94\u4F7F\u7528\u5728 Info.plist \u4E2D\u914D\u7F6E\u542F\u52A8\u7A0B\u5E8F\u7684\u65E7\u65B9\u6CD5\u3002
+
+param.category-name=\u7C7B\u522B
+param.category-name.description=Mac App Store \u7C7B\u522B\u3002\u8BF7\u6CE8\u610F, \u952E\u662F\u5411\u7528\u6237\u663E\u793A\u7684\u5B57\u7B26\u4E32, \u503C\u662F\u7C7B\u522B\u7684 ID\u3002
+
+param.cfbundle-name.name=CFBundleName
+param.cfbundle-name.description=\u5E94\u7528\u7A0B\u5E8F\u5728\u83DC\u5355\u680F\u4E2D\u7684\u663E\u793A\u540D\u79F0\u3002\u53EF\u4EE5\u4E0E\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0\u4E0D\u540C\u3002\u6B64\u540D\u79F0\u7684\u957F\u5EA6\u5E94\u5C11\u4E8E 16 \u4E2A\u5B57\u7B26, \u5E76\u4E14\u5E94\u9002\u5408\u5728\u83DC\u5355\u680F\u548C\u5E94\u7528\u7A0B\u5E8F\u7684\u201C\u4FE1\u606F\u201D\u7A97\u53E3\u4E2D\u663E\u793A\u3002
+
+param.cfbundle-identifier.name=CFBundleIdentifier
+param.cfbundle-identifier.description=\u552F\u4E00\u6807\u8BC6 MacOSX \u5E94\u7528\u7A0B\u5E8F (\u5728 Mac App Store \u4E0A) \u7684\u6807\u8BC6\u7B26\u3002\u53EA\u80FD\u4F7F\u7528\u5B57\u6BCD\u6570\u5B57 (A-Z,a-z,0-9), \u8FDE\u5B57\u7B26 (-) \u548C\u53E5\u70B9 (.) \u5B57\u7B26\u3002
+
+param.cfbundle-version.name=CFBundleVersion
+param.cfbundle-version.description=CFBundle \u7684\u8BA1\u7B97\u673A\u53EF\u8BFB\u7248\u672C\u3002\u53EA\u80FD\u5305\u542B\u6570\u5B57\u4EE5\u53CA\u96F6\u5230\u4E24\u4E2A\u70B9, \u4F8B\u5982 "1.8.1" \u6216 "100"\u3002
+
+param.bundle-id-signing-prefix.name=\u5305\u7B7E\u540D\u524D\u7F00
+param.bundle-id-signing-prefix.description=\u5BF9\u5E94\u7528\u7A0B\u5E8F\u5305\u8FDB\u884C\u7B7E\u540D\u65F6, \u6B64\u503C\u5C06\u4F5C\u4E3A\u524D\u7F00\u6DFB\u52A0\u5230\u9700\u8981\u7B7E\u540D\u4F46\u4E0D\u5177\u6709\u73B0\u6709 CFBundleIdentifier \u7684\u6240\u6709\u7EC4\u4EF6\u4E2D\u3002
+
+param.raw-executable-url.name=\u542F\u52A8\u7A0B\u5E8F URL
+param.raw-executable-url.description=\u4F7F\u7528\u5B9A\u5236\u542F\u52A8\u7A0B\u5E8F\u8986\u76D6\u6253\u5305\u7A0B\u5E8F\u9ED8\u8BA4\u542F\u52A8\u7A0B\u5E8F\u3002
+
+param.default-icon-icns=\u9ED8\u8BA4\u56FE\u6807
+param.default-icon-icns.description=\u7528\u6237\u672A\u6307\u5B9A icns \u6587\u4EF6\u65F6\u4F7F\u7528\u7684\u9ED8\u8BA4\u56FE\u6807\u3002
+
+param.runtime.name=JRE
+param.runtime.description=\u8981\u5171\u540C\u6253\u5305\u7684 Java \u8FD0\u884C\u65F6\u3002\u9ED8\u8BA4\u503C\u4E3A\u8FD0\u884C\u6253\u5305\u7A0B\u5E8F\u7684\u5F53\u524D JRE\u3002\u503C\u4E3A\u7A7A\u503C\u5C06\u5BFC\u81F4\u4E0D\u4F1A\u5171\u540C\u6253\u5305\u4EFB\u4F55 JRE, \u5E76\u4E14\u5C06\u4F7F\u7528\u7CFB\u7EDF JRE \u6765\u542F\u52A8\u5E94\u7528\u7A0B\u5E8F\u3002
+
+param.images-root.name=
+param.images-root.description=
+
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+error.invalid-cfbundle-version=\u65E0\u6548\u7684 CFBundleVersion - ''{0}''
+error.invalid-cfbundle-version.advice=\u8BBE\u7F6E\u517C\u5BB9\u7684 'appVersion' \u6216\u8005\u8BBE\u7F6E 'mac.CFBundleVersion'\u3002\u6709\u6548\u7248\u672C\u5305\u542B\u4E00\u5230\u4E09\u4E2A\u7528\u70B9\u5206\u9694\u7684\u6574\u6570\u3002
+error.explicit-sign-no-cert=\u5DF2\u660E\u786E\u8BF7\u6C42\u7B7E\u540D, \u4F46\u672A\u6307\u5B9A\u7B7E\u540D\u8BC1\u4E66\u3002
+error.explicit-sign-no-cert.advice=\u5728 'mac.signing-key-developer-id-app' \u4E2D\u6307\u5B9A\u6709\u6548\u7684\u8BC1\u4E66, \u6216\u8005\u53D6\u6D88\u8BBE\u7F6E 'signBundle', \u6216\u8005\u5C06 'signBundle' \u8BBE\u7F6E\u4E3A\u201C\u5047\u201D\u3002
+error.non-existent-runtime=\u8FD0\u884C\u65F6/JRE \u76EE\u5F55\u7684\u6587\u4EF6\u4E0D\u5B58\u5728\u3002
+error.non-existent-runtime.advice=\u5C06\u8FD0\u884C\u65F6\u53C2\u6570\u6307\u5411\u5305\u542B JRE \u7684\u76EE\u5F55\u3002
+error.cannot-detect-runtime-in-directory=\u65E0\u6CD5\u786E\u5B9A\u6307\u5B9A\u7684\u8FD0\u884C\u65F6\u76EE\u5F55\u4E2D\u5B58\u5728\u54EA\u4E2A\u7248\u672C\u7684 JRE/JDK\u3002
+error.cannot-detect-runtime-in-directory.advice=\u5C06\u8FD0\u884C\u65F6\u76EE\u5F55\u6307\u5411\u4EE5\u4E0B\u76EE\u5F55\u4E4B\u4E00: JDK/JRE \u6839\u76EE\u5F55, \u8BE5\u6839\u76EE\u5F55\u7684 Contents/Home \u76EE\u5F55\u6216 JDK \u7684 Contents/Home/jre \u76EE\u5F55\u3002
+resource.app-info-plist=\u5E94\u7528\u7A0B\u5E8F Info.plist
+resource.runtime-info-plist=Java \u8FD0\u884C\u65F6 Info.plist
+
+message.config-save-location=\u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58\u5230 {0}\u3002\u4F7F\u7528\u8FD9\u4E9B\u914D\u7F6E\u6587\u4EF6\u53EF\u5B9A\u5236\u7A0B\u5E8F\u5305\u3002
+message.bundle-name-too-long-warning={0}\u5DF2\u8BBE\u7F6E\u4E3A ''{1}'', \u5176\u957F\u5EA6\u8D85\u8FC7\u4E86 16 \u4E2A\u5B57\u7B26\u3002\u4E3A\u4E86\u83B7\u5F97\u66F4\u597D\u7684 Mac \u4F53\u9A8C, \u8BF7\u8003\u8651\u5C06\u5176\u7F29\u77ED\u3002
+message.no-mac-jre-support=Mac \u5F53\u524D\u9700\u8981 JDK \u4EE5\u4FBF\u6253\u5305
+message.creating-app-bundle=\u6B63\u5728\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u5305: {0}
+message.null-classpath=\u662F\u5426\u4E3A\u7A7A\u5E94\u7528\u7A0B\u5E8F\u8D44\u6E90?
+message.preparing-info-plist=\u6B63\u5728\u51C6\u5907 Info.plist: {0}
+message.icon-not-icns= \u6307\u5B9A\u7684\u56FE\u6807 "{0}" \u4E0D\u662F ICNS \u6587\u4EF6, \u4E0D\u4F1A\u4F7F\u7528\u3002\u5C06\u4F7F\u7528\u9ED8\u8BA4\u56FE\u6807\u4EE3\u66FF\u3002
+message.version-string-too-many-components=\u7248\u672C\u5B57\u7B26\u4E32\u53EF\u4EE5\u5305\u542B 1 \u5230 3 \u4E2A\u6570\u5B57: 1, 1.2, 1.2.3\u3002
+message.version-string-first-number-not-zero=CFBundleVersion \u4E2D\u7684\u7B2C\u4E00\u4E2A\u6570\u5B57\u4E0D\u80FD\u4E3A\u96F6\u6216\u8D1F\u6570\u3002
+message.version-string-no-negative-numbers=\u7248\u672C\u5B57\u7B26\u4E32\u4E2D\u4E0D\u5141\u8BB8\u4F7F\u7528\u8D1F\u6570\u3002
+message.version-string-numbers-only=\u7248\u672C\u5B57\u7B26\u4E32\u53EA\u80FD\u5305\u542B\u6570\u5B57\u548C\u6700\u591A\u4E24\u4E2A\u70B9\u3002
+message.creating-association-with-null-extension=\u6B63\u5728\u4F7F\u7528\u7A7A\u6269\u5C55\u540D\u521B\u5EFA\u5173\u8054\u3002
+
+message.using-default-resource=\u4F7F\u7528\u9ED8\u8BA4\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u5C06 {1} \u6DFB\u52A0\u5230\u7C7B\u8DEF\u5F84\u4EE5\u5B9A\u5236)
+message.using-custom-resource-from-file=\u4F7F\u7528\u5B9A\u5236\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u4ECE\u6587\u4EF6 {1} \u52A0\u8F7D)
+message.using-custom-resource-from-classpath=\u4F7F\u7528\u5B9A\u5236\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u4ECE {1} \u52A0\u8F7D)
+message.using-default-resource-from-classpath=\u4F7F\u7528\u9ED8\u8BA4\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u5C06 {1} \u6DFB\u52A0\u5230\u7C7B\u8DEF\u5F84\u4EE5\u5B9A\u5236)
+message.ignoring.symlink=\u8B66\u544A: codesign \u6B63\u5728\u8DF3\u8FC7\u7B26\u53F7\u94FE\u63A5 {0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/DMGsetup.scpt	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,15 @@
+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
+
+    set the bounds of container window to {400, 100, 917, 370}
+
+    set theViewOptions to the icon view options of container window
+    set arrangement of theViewOptions to not arranged
+    set icon size of theViewOptions to 128
+  end tell
+end tell
+
Binary file src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/GenericApp.icns has changed
Binary file src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/GenericAppHiDPI.icns has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/Info-lite.plist.template	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,38 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://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 http://developer.apple.com/library/mac/#releasenotes/General/SubmittingToMacAppStore/_index.html
+       for list of AppStore categories -->
+  <key>LSApplicationCategoryType</key>
+  <string>DEPLOY_BUNDLE_CATEGORY</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.packager/macosx/classes/jdk/packager/internal/resources/mac/Info.plist.template	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,60 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+  <key>LSMinimumSystemVersion</key>
+  <string>10.7.4</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 http://developer.apple.com/library/mac/#releasenotes/General/SubmittingToMacAppStore/_index.html
+       for list of AppStore categories -->
+  <key>LSApplicationCategoryType</key>
+  <string>DEPLOY_BUNDLE_CATEGORY</string>
+  <key>CFBundleVersion</key>
+  <string>DEPLOY_BUNDLE_CFBUNDLE_VERSION</string>
+  <key>NSHumanReadableCopyright</key>
+  <string>DEPLOY_BUNDLE_COPYRIGHT</string>
+  <key>JVMRuntime</key>
+  <string>DEPLOY_JAVA_RUNTIME_NAME</string>
+  <key>JVMMainClassName</key>
+  <string>DEPLOY_LAUNCHER_CLASS</string>
+  <key>JVMAppClasspath</key>
+  <string>DEPLOY_APP_CLASSPATH</string>
+  <key>JVMMainJarName</key>
+  <string>DEPLOY_MAIN_JAR_NAME</string>
+  <key>JVMPreferencesID</key>
+  <string>DEPLOY_PREFERENCES_ID</string>
+  <key>JVMOptions</key>
+  <array>
+DEPLOY_JVM_OPTIONS
+  </array>
+  <key>JVMUserOptions</key>
+    <dict>
+DEPLOY_JVM_USER_OPTIONS
+    </dict>
+  <key>ArgOptions</key>
+  <array>
+DEPLOY_ARGUMENTS
+  </array>DEPLOY_FILE_ASSOCIATIONS
+  <key>NSHighResolutionCapable</key>
+  <string>true</string>
+ </dict>
+</plist>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacAppBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,63 @@
+bundler.name=Mac Application Image
+bundler.description=A Directory based image of a mac Application with an optionally co-bundled JRE.  Used as a base for the Installer bundlers
+
+param.signing-key-developer-id-app.name=Apple Developer ID Application Signing Key
+param.signing-key-developer-id-app.description=The full name of the Apple Developer ID Application signing key.
+
+param.icon-icns.name=.icns Icon
+param.icon-icns.description=Icon for the application, in ICNS format.
+
+param.config-root.name=
+param.config-root.description=
+
+param.configure-launcher-in-plist=Configure Launcher in Info.plist
+param.configure-launcher-in-plist.description=Should the legacy method of configuring hte launcher in the Info.plist be used.
+
+param.category-name=Category
+param.category-name.description=Mac App Store Categories. Note that the key is the string to display to the user and the value is the id of the category.
+
+param.cfbundle-name.name=CFBundleName
+param.cfbundle-name.description=The name of the app as it appears in the Menu Bar.  This can be different from the application name.  This name should be less than 16 characters long and be suitable for displaying in the menu bar and the app's Info window.
+
+param.cfbundle-identifier.name=CFBundleIdentifier
+param.cfbundle-identifier.description=An identifier that uniquely identifies the application for MacOSX (and on the Mac App Store).  May only use alphanumeric (A-Z,a-z,0-9), hyphen (-), and period (.) characters.
+
+param.cfbundle-version.name=CFBundleVersion
+param.cfbundle-version.description=An computer readable version for the CFBundle.  May contain only digits and from zero to two dots, such as "1.8.1" or "100".
+
+param.bundle-id-signing-prefix.name=Bundle Signing Prefix
+param.bundle-id-signing-prefix.description=When signing the application bundle this value is prefixed to all components that need to be signed that don't have an existing CFBundleIdentifier.
+
+param.raw-executable-url.name=Launcher URL
+param.raw-executable-url.description=Override the packager default launcher with a custom launcher.
+
+param.default-icon-icns=Default Icon
+param.default-icon-icns.description=The Default Icon for when a user does not specify an icns file.
+
+param.runtime.name=JRE
+param.runtime.description=The Java Runtime to co-bundle.  The default value is the current JRE running the bundler.  A value of null will cause no JRE to be co-bundled and the system JRE will be used to launch the application.
+
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+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.non-existent-runtime=The file for the Runtime/JRE directory does not exist.
+error.non-existent-runtime.advice=Point the runtime parameter to a directory that containes the JRE.
+error.cannot-detect-runtime-in-directory=Cannot determine which JRE/JDK exists in the specified runtime directory.
+error.cannot-detect-runtime-in-directory.advice=Point the runtime directory to one of the JDK/JRE root, the Contents/Home directory of that root, or the Contents/Home/jre directory of the JDK.
+resource.bundle-config-file=Bundle config file
+
+message.config-save-location=Config files are saved to {0}. Use them to customize package.
+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.no-mac-jre-support=Currently Macs require a JDK to package
+message.creating-app-bundle=Creating app bundle\: {0}
+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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacAppBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,63 @@
+bundler.name=Mac\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8
+bundler.description=\u30AA\u30D7\u30B7\u30E7\u30F3\u3067JRE\u304C\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u3066\u3044\u308BMac\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FB\u30D9\u30FC\u30B9\u306E\u30A4\u30E1\u30FC\u30B8\u3002\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FB\u30D0\u30F3\u30C9\u30EB\u306E\u30D9\u30FC\u30B9\u3068\u3057\u3066\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+
+param.signing-key-developer-id-app.name=Apple Developer ID\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u7F72\u540D\u30AD\u30FC
+param.signing-key-developer-id-app.description=Apple Developer ID\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u7F72\u540D\u30AD\u30FC\u306E\u30D5\u30EB\u30FB\u30CD\u30FC\u30E0\u3002
+
+param.icon-icns.name=.icns\u30A2\u30A4\u30B3\u30F3
+param.icon-icns.description=ICNS\u5F62\u5F0F\u3067\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30A2\u30A4\u30B3\u30F3\u3002
+
+param.config-root.name=
+param.config-root.description=
+
+param.configure-launcher-in-plist=Info.plist\u3067\u306E\u30E9\u30F3\u30C1\u30E3\u306E\u69CB\u6210
+param.configure-launcher-in-plist.description=Info.plist\u3067\u306E\u30E9\u30F3\u30C1\u30E3\u306E\u69CB\u6210\u306B\u306F\u30EC\u30AC\u30B7\u30FC\u30FB\u30E1\u30BD\u30C3\u30C9\u3092\u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
+
+param.category-name=\u30AB\u30C6\u30B4\u30EA
+param.category-name.description=Mac App Store\u306E\u30AB\u30C6\u30B4\u30EA\u3002\u30AD\u30FC\u306F\u30E6\u30FC\u30B6\u30FC\u306B\u8868\u793A\u3055\u308C\u308B\u6587\u5B57\u5217\u3067\u3001\u5024\u306F\u30AB\u30C6\u30B4\u30EA\u306EID\u3067\u3059\u3002
+
+param.cfbundle-name.name=CFBundleName
+param.cfbundle-name.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u304C\u30E1\u30CB\u30E5\u30FC\u30FB\u30D0\u30FC\u306B\u8868\u793A\u3055\u308C\u308B\u969B\u306E\u540D\u524D\u3002\u3053\u308C\u306F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D\u3068\u306F\u7570\u306A\u308B\u5834\u5408\u304C\u3042\u308A\u307E\u3059\u3002\u3053\u306E\u540D\u524D\u306F16\u6587\u5B57\u672A\u6E80\u3068\u3057\u3001\u30E1\u30CB\u30E5\u30FC\u30FB\u30D0\u30FC\u3068\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u60C5\u5831\u30A6\u30A3\u30F3\u30C9\u30A6\u3067\u306E\u8868\u793A\u306B\u9069\u3057\u305F\u3082\u306E\u306B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
+
+param.cfbundle-identifier.name=CFBundleIdentifier
+param.cfbundle-identifier.description=MacOSX(\u304A\u3088\u3073Mac App Store)\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u4E00\u610F\u306B\u8B58\u5225\u3059\u308B\u8B58\u5225\u5B50\u3002\u82F1\u6570\u5B57(A-Z\u3001a-z\u30010-9)\u3001\u30CF\u30A4\u30D5\u30F3(-)\u304A\u3088\u3073\u30D4\u30EA\u30AA\u30C9(.)\u306E\u307F\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002
+
+param.cfbundle-version.name=CFBundleVersion
+param.cfbundle-version.description=\u30B3\u30F3\u30D4\u30E5\u30FC\u30BF\u3067\u8AAD\u53D6\u308A\u53EF\u80FD\u306ACFBundle\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3002\u6570\u5B57\u304A\u3088\u3073\u30BC\u30ED\u304B\u30892\u3064\u307E\u3067\u306E\u30C9\u30C3\u30C8\u306E\u307F\u3092\u542B\u3081\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059("1.8.1"\u3001"100"\u306A\u3069)\u3002
+
+param.bundle-id-signing-prefix.name=\u30D0\u30F3\u30C9\u30EB\u7F72\u540D\u63A5\u982D\u8F9E
+param.bundle-id-signing-prefix.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB\u306B\u7F72\u540D\u3059\u308B\u969B\u3001\u7F72\u540D\u3059\u308B\u5FC5\u8981\u306E\u3042\u308B\u3001\u65E2\u5B58\u306ECFBundleIdentifier\u3092\u6301\u305F\u306A\u3044\u3059\u3079\u3066\u306E\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u306B\u3053\u306E\u5024\u304C\u63A5\u982D\u8F9E\u3068\u3057\u3066\u4ED8\u3051\u3089\u308C\u307E\u3059\u3002
+
+param.raw-executable-url.name=\u30E9\u30F3\u30C1\u30E3URL
+param.raw-executable-url.description=\u30D1\u30C3\u30B1\u30FC\u30B8\u30E3\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30E9\u30F3\u30C1\u30E3\u3092\u30AB\u30B9\u30BF\u30E0\u30FB\u30E9\u30F3\u30C1\u30E3\u3067\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u3059\u3002
+
+param.default-icon-icns=\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3
+param.default-icon-icns.description=\u30E6\u30FC\u30B6\u30FC\u304C\u30A2\u30A4\u30B3\u30F3\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u306A\u3044\u5834\u5408\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3\u3002
+
+param.runtime.name=JRE
+param.runtime.description=\u30D0\u30F3\u30C9\u30EB\u3059\u308BJava\u30E9\u30F3\u30BF\u30A4\u30E0\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u306F\u3001\u30D0\u30F3\u30C9\u30E9\u3092\u5B9F\u884C\u3057\u3066\u3044\u308B\u73FE\u5728\u306EJRE\u3067\u3059\u3002\u5024\u304Cnull\u306E\u5834\u5408\u3001JRE\u306F\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305A\u3001\u30B7\u30B9\u30C6\u30E0\u306EJRE\u304C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u8D77\u52D5\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+error.invalid-cfbundle-version=CFBundleVersion - ''{0}''\u304C\u7121\u52B9\u3067\u3059
+error.invalid-cfbundle-version.advice=\u4E92\u63DB\u6027\u306E\u3042\u308B'appVersion'\u3092\u8A2D\u5B9A\u3059\u308B\u304B\u3001'mac.CFBundleVersion'\u3092\u8A2D\u5B9A\u3057\u307E\u3059\u3002\u6709\u52B9\u306A\u30D0\u30FC\u30B8\u30E7\u30F3\u306F\u3001\u30C9\u30C3\u30C8\u3067\u533A\u5207\u3089\u308C\u305F1\u304B\u30893\u3064\u306E\u6574\u6570\u3067\u3059\u3002
+error.explicit-sign-no-cert=\u7F72\u540D\u304C\u660E\u793A\u7684\u306B\u8981\u6C42\u3055\u308C\u307E\u3057\u305F\u304C\u3001\u7F72\u540D\u8A3C\u660E\u66F8\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002
+error.explicit-sign-no-cert.advice=\u6709\u52B9\u306A\u8A3C\u660E\u66F8\u3092'mac.signing-key-developer-id-app'\u3067\u6307\u5B9A\u3059\u308B\u304B\u3001'signBundle'\u3092\u8A2D\u5B9A\u89E3\u9664\u3059\u308B\u304B\u3001\u307E\u305F\u306F'signBundle'\u3092false\u306B\u8A2D\u5B9A\u3057\u307E\u3059\u3002
+error.non-existent-runtime=\u30E9\u30F3\u30BF\u30A4\u30E0/JRE\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u30D5\u30A1\u30A4\u30EB\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002
+error.non-existent-runtime.advice=\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3001JRE\u3092\u542B\u3080\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002
+error.cannot-detect-runtime-in-directory=\u6307\u5B9A\u3057\u305F\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u3069\u306EJRE/JDK\u304C\u5B58\u5728\u3059\u308B\u306E\u304B\u3092\u7279\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-detect-runtime-in-directory.advice=\u30E9\u30A4\u30BF\u30A4\u30E0\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u3001JDK/JRE\u30EB\u30FC\u30C8\u3001\u305D\u306E\u30EB\u30FC\u30C8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4/\u30DB\u30FC\u30E0\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3001\u307E\u305F\u306FJDK\u306E\u30B3\u30F3\u30C6\u30F3\u30C4/\u30DB\u30FC\u30E0/jre\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002
+resource.bundle-config-file=\u30D0\u30F3\u30C9\u30EB\u69CB\u6210\u30D5\u30A1\u30A4\u30EB
+
+message.config-save-location=\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C{0}\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B\u306B\u306F\u3053\u308C\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+message.bundle-name-too-long-warning={0}\u304C16\u6587\u5B57\u3092\u8D85\u3048\u308B''{1}''\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059\u3002Mac\u3067\u306E\u64CD\u4F5C\u6027\u3092\u3088\u308A\u826F\u304F\u3059\u308B\u305F\u3081\u306B\u77ED\u304F\u3059\u308B\u3053\u3068\u3092\u691C\u8A0E\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+message.no-mac-jre-support=\u73FE\u5728\u3001Mac\u3067\u306FJDK\u3092\u30D1\u30C3\u30B1\u30FC\u30B8\u5316\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
+message.creating-app-bundle=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059: {0}
+message.null-classpath=Null\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30EA\u30BD\u30FC\u30B9\u3067\u3059\u304B\u3002
+message.preparing-info-plist=Info.plist\u3092\u6E96\u5099\u3057\u3066\u3044\u307E\u3059: {0}
+message.icon-not-icns= \u6307\u5B9A\u3057\u305F\u30A2\u30A4\u30B3\u30F3"{0}"\u306FICNS\u30D5\u30A1\u30A4\u30EB\u3067\u306F\u306A\u304F\u3001\u4F7F\u7528\u3055\u308C\u307E\u305B\u3093\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3\u304C\u305D\u306E\u4F4D\u7F6E\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+message.version-string-too-many-components=\u30D0\u30FC\u30B8\u30E7\u30F3\u6587\u5B57\u5217\u306B\u306F\u30011\u30011.2\u30011.2.3\u306A\u30691\u304B\u30893\u306E\u6570\u5B57\u3092\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002
+message.version-string-first-number-not-zero=CFBundleVersion\u306E\u6700\u521D\u306E\u6570\u5B57\u306F\u3001\u30BC\u30ED\u307E\u305F\u306F\u8CA0\u306E\u5024\u306B\u3067\u304D\u307E\u305B\u3093\u3002
+message.version-string-no-negative-numbers=\u30D0\u30FC\u30B8\u30E7\u30F3\u6587\u5B57\u5217\u306B\u8CA0\u306E\u6570\u306F\u8A31\u53EF\u3055\u308C\u307E\u305B\u3093\u3002
+message.version-string-numbers-only=\u30D0\u30FC\u30B8\u30E7\u30F3\u6587\u5B57\u5217\u306F\u3001\u6570\u5B57\u30682\u3064\u307E\u3067\u306E\u30C9\u30C3\u30C8\u3067\u306E\u307F\u69CB\u6210\u3067\u304D\u307E\u3059\u3002
+message.creating-association-with-null-extension=null\u62E1\u5F35\u5B50\u3068\u306E\u95A2\u9023\u4ED8\u3051\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacAppBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,63 @@
+bundler.name=Mac \u5E94\u7528\u7A0B\u5E8F\u6620\u50CF
+bundler.description=\u4E00\u4E2A\u57FA\u4E8E\u76EE\u5F55\u7684 mac \u5E94\u7528\u7A0B\u5E8F\u6620\u50CF, \u53EF\u4EE5\u9009\u62E9\u6027\u5730\u5E26\u6709\u5171\u540C\u6253\u5305\u7684 JRE\u3002\u7528\u4F5C\u5B89\u88C5\u7A0B\u5E8F\u6253\u5305\u7A0B\u5E8F\u7684\u57FA\u7840
+
+param.signing-key-developer-id-app.name=Apple \u5F00\u53D1\u8005 ID \u5E94\u7528\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5
+param.signing-key-developer-id-app.description=Apple \u5F00\u53D1\u8005 ID \u5E94\u7528\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5\u7684\u5168\u540D\u3002
+
+param.icon-icns.name=.icns \u56FE\u6807
+param.icon-icns.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u56FE\u6807, \u91C7\u7528 ICNS \u683C\u5F0F\u3002
+
+param.config-root.name=
+param.config-root.description=
+
+param.configure-launcher-in-plist=\u5728 Info.plist \u4E2D\u914D\u7F6E\u542F\u52A8\u7A0B\u5E8F
+param.configure-launcher-in-plist.description=\u662F\u5426\u5E94\u4F7F\u7528\u5728 Info.plist \u4E2D\u914D\u7F6E\u542F\u52A8\u7A0B\u5E8F\u7684\u65E7\u65B9\u6CD5\u3002
+
+param.category-name=\u7C7B\u522B
+param.category-name.description=Mac App Store \u7C7B\u522B\u3002\u8BF7\u6CE8\u610F, \u952E\u662F\u5411\u7528\u6237\u663E\u793A\u7684\u5B57\u7B26\u4E32, \u503C\u662F\u7C7B\u522B\u7684 ID\u3002
+
+param.cfbundle-name.name=CFBundleName
+param.cfbundle-name.description=\u5E94\u7528\u7A0B\u5E8F\u5728\u83DC\u5355\u680F\u4E2D\u7684\u663E\u793A\u540D\u79F0\u3002\u53EF\u4EE5\u4E0E\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0\u4E0D\u540C\u3002\u6B64\u540D\u79F0\u7684\u957F\u5EA6\u5E94\u5C11\u4E8E 16 \u4E2A\u5B57\u7B26, \u5E76\u4E14\u5E94\u9002\u5408\u5728\u83DC\u5355\u680F\u548C\u5E94\u7528\u7A0B\u5E8F\u7684\u201C\u4FE1\u606F\u201D\u7A97\u53E3\u4E2D\u663E\u793A\u3002
+
+param.cfbundle-identifier.name=CFBundleIdentifier
+param.cfbundle-identifier.description=\u552F\u4E00\u6807\u8BC6 MacOSX \u5E94\u7528\u7A0B\u5E8F (\u5728 Mac App Store \u4E0A) \u7684\u6807\u8BC6\u7B26\u3002\u53EA\u80FD\u4F7F\u7528\u5B57\u6BCD\u6570\u5B57 (A-Z,a-z,0-9), \u8FDE\u5B57\u7B26 (-) \u548C\u53E5\u70B9 (.) \u5B57\u7B26\u3002
+
+param.cfbundle-version.name=CFBundleVersion
+param.cfbundle-version.description=CFBundle \u7684\u8BA1\u7B97\u673A\u53EF\u8BFB\u7248\u672C\u3002\u53EA\u80FD\u5305\u542B\u6570\u5B57\u4EE5\u53CA\u96F6\u5230\u4E24\u4E2A\u70B9, \u4F8B\u5982 "1.8.1" \u6216 "100"\u3002
+
+param.bundle-id-signing-prefix.name=\u5305\u7B7E\u540D\u524D\u7F00
+param.bundle-id-signing-prefix.description=\u5BF9\u5E94\u7528\u7A0B\u5E8F\u5305\u8FDB\u884C\u7B7E\u540D\u65F6, \u6B64\u503C\u5C06\u4F5C\u4E3A\u524D\u7F00\u6DFB\u52A0\u5230\u9700\u8981\u7B7E\u540D\u4F46\u4E0D\u5177\u6709\u73B0\u6709 CFBundleIdentifier \u7684\u6240\u6709\u7EC4\u4EF6\u4E2D\u3002
+
+param.raw-executable-url.name=\u542F\u52A8\u7A0B\u5E8F URL
+param.raw-executable-url.description=\u4F7F\u7528\u5B9A\u5236\u542F\u52A8\u7A0B\u5E8F\u8986\u76D6\u6253\u5305\u7A0B\u5E8F\u9ED8\u8BA4\u542F\u52A8\u7A0B\u5E8F\u3002
+
+param.default-icon-icns=\u9ED8\u8BA4\u56FE\u6807
+param.default-icon-icns.description=\u7528\u6237\u672A\u6307\u5B9A icns \u6587\u4EF6\u65F6\u4F7F\u7528\u7684\u9ED8\u8BA4\u56FE\u6807\u3002
+
+param.runtime.name=JRE
+param.runtime.description=\u8981\u5171\u540C\u6253\u5305\u7684 Java \u8FD0\u884C\u65F6\u3002\u9ED8\u8BA4\u503C\u4E3A\u8FD0\u884C\u6253\u5305\u7A0B\u5E8F\u7684\u5F53\u524D JRE\u3002\u503C\u4E3A\u7A7A\u503C\u5C06\u5BFC\u81F4\u4E0D\u4F1A\u5171\u540C\u6253\u5305\u4EFB\u4F55 JRE, \u5E76\u4E14\u5C06\u4F7F\u7528\u7CFB\u7EDF JRE \u6765\u542F\u52A8\u5E94\u7528\u7A0B\u5E8F\u3002
+
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+error.invalid-cfbundle-version=\u65E0\u6548\u7684 CFBundleVersion - ''{0}''
+error.invalid-cfbundle-version.advice=\u8BBE\u7F6E\u517C\u5BB9\u7684 'appVersion' \u6216\u8005\u8BBE\u7F6E 'mac.CFBundleVersion'\u3002\u6709\u6548\u7248\u672C\u5305\u542B\u4E00\u5230\u4E09\u4E2A\u7528\u70B9\u5206\u9694\u7684\u6574\u6570\u3002
+error.explicit-sign-no-cert=\u5DF2\u660E\u786E\u8BF7\u6C42\u7B7E\u540D, \u4F46\u672A\u6307\u5B9A\u7B7E\u540D\u8BC1\u4E66\u3002
+error.explicit-sign-no-cert.advice=\u5728 'mac.signing-key-developer-id-app' \u4E2D\u6307\u5B9A\u6709\u6548\u7684\u8BC1\u4E66, \u6216\u8005\u53D6\u6D88\u8BBE\u7F6E 'signBundle', \u6216\u8005\u5C06 'signBundle' \u8BBE\u7F6E\u4E3A\u201C\u5047\u201D\u3002
+error.non-existent-runtime=\u8FD0\u884C\u65F6/JRE \u76EE\u5F55\u7684\u6587\u4EF6\u4E0D\u5B58\u5728\u3002
+error.non-existent-runtime.advice=\u5C06\u8FD0\u884C\u65F6\u53C2\u6570\u6307\u5411\u5305\u542B JRE \u7684\u76EE\u5F55\u3002
+error.cannot-detect-runtime-in-directory=\u65E0\u6CD5\u786E\u5B9A\u6307\u5B9A\u7684\u8FD0\u884C\u65F6\u76EE\u5F55\u4E2D\u5B58\u5728\u54EA\u4E2A\u7248\u672C\u7684 JRE/JDK\u3002
+error.cannot-detect-runtime-in-directory.advice=\u5C06\u8FD0\u884C\u65F6\u76EE\u5F55\u6307\u5411\u4EE5\u4E0B\u76EE\u5F55\u4E4B\u4E00: JDK/JRE \u6839\u76EE\u5F55, \u8BE5\u6839\u76EE\u5F55\u7684 Contents/Home \u76EE\u5F55\u6216 JDK \u7684 Contents/Home/jre \u76EE\u5F55\u3002
+resource.bundle-config-file=\u5305\u914D\u7F6E\u6587\u4EF6
+
+message.config-save-location=\u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58\u5230 {0}\u3002\u4F7F\u7528\u8FD9\u4E9B\u914D\u7F6E\u6587\u4EF6\u53EF\u5B9A\u5236\u7A0B\u5E8F\u5305\u3002
+message.bundle-name-too-long-warning={0}\u5DF2\u8BBE\u7F6E\u4E3A ''{1}'', \u5176\u957F\u5EA6\u8D85\u8FC7\u4E86 16 \u4E2A\u5B57\u7B26\u3002\u4E3A\u4E86\u83B7\u5F97\u66F4\u597D\u7684 Mac \u4F53\u9A8C, \u8BF7\u8003\u8651\u5C06\u5176\u7F29\u77ED\u3002
+message.no-mac-jre-support=Mac \u5F53\u524D\u9700\u8981 JDK \u4EE5\u4FBF\u6253\u5305
+message.creating-app-bundle=\u6B63\u5728\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u5305: {0}
+message.null-classpath=\u662F\u5426\u4E3A\u7A7A\u5E94\u7528\u7A0B\u5E8F\u8D44\u6E90?
+message.preparing-info-plist=\u6B63\u5728\u51C6\u5907 Info.plist: {0}
+message.icon-not-icns= \u6307\u5B9A\u7684\u56FE\u6807 "{0}" \u4E0D\u662F ICNS \u6587\u4EF6, \u4E0D\u4F1A\u4F7F\u7528\u3002\u5C06\u4F7F\u7528\u9ED8\u8BA4\u56FE\u6807\u4EE3\u66FF\u3002
+message.version-string-too-many-components=\u7248\u672C\u5B57\u7B26\u4E32\u53EF\u4EE5\u5305\u542B 1 \u5230 3 \u4E2A\u6570\u5B57: 1, 1.2, 1.2.3\u3002
+message.version-string-first-number-not-zero=CFBundleVersion \u4E2D\u7684\u7B2C\u4E00\u4E2A\u6570\u5B57\u4E0D\u80FD\u4E3A\u96F6\u6216\u8D1F\u6570\u3002
+message.version-string-no-negative-numbers=\u7248\u672C\u5B57\u7B26\u4E32\u4E2D\u4E0D\u5141\u8BB8\u4F7F\u7528\u8D1F\u6570\u3002
+message.version-string-numbers-only=\u7248\u672C\u5B57\u7B26\u4E32\u53EA\u80FD\u5305\u542B\u6570\u5B57\u548C\u6700\u591A\u4E24\u4E2A\u70B9\u3002
+message.creating-association-with-null-extension=\u6B63\u5728\u4F7F\u7528\u7A7A\u6269\u5C55\u540D\u521B\u5EFA\u5173\u8054\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacAppStore.entitlements	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://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.packager/macosx/classes/jdk/packager/internal/resources/mac/MacAppStoreBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,36 @@
+bundler.name=Mac App Store Ready Bundler
+bundler.description=Creates a binary bundle ready for deployment into the Mac App Store."
+
+param.signing-key-app.name=Application Signing Key
+param.signing-key-app.description=The full name of the signing key to sign the application with.
+
+param.signing-key-pkg.name=Installer Signing Key
+param.signing-key-pkg.description=The full name of the signing key to sign the PKG Installer with.
+
+param.mac-app-store-entitlements.name=Entitlements File
+param.mac-app-store-entitlements.description=File location of a custom mac app store entitlements file
+
+param.installer-suffix.name=Installer Suffix
+param.installer-suffix.description=The suffix for the installer name for this package.  <name><suffix>.pkg.
+
+resource.mac-app-store-entitlements=Mac App Store Entitlements
+resource.mac-app-store-inherit-entitlements=Mac App Store Inherit Entitlements
+
+error.parameters-null=Parameters map is null.
+error.parameters-null.advice=Pass in a non-null parameters map.
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+error.no-system-runtime=Bundle Configured to use the System JRE
+error.no-system-runtime.advice=Do not set 'runtime' to null, either don't set it or set it to a valid value.
+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}.
+
+
+message.config-save-location=Config files are saved to {0}. Use them to customize package.
+message.building-bundle=Building Mac App Store Bundle for {0}
+mesasge.intermediate-bundle-location=Intermediate application bundle image\: {0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacAppStoreBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,36 @@
+bundler.name=Mac App Store\u306E\u6E96\u5099\u5B8C\u4E86\u30D0\u30F3\u30C9\u30E9
+bundler.description=Mac App Store\u3078\u306E\u30C7\u30D7\u30ED\u30A4\u30E1\u30F3\u30C8\u6E96\u5099\u5B8C\u4E86\u306E\u30D0\u30A4\u30CA\u30EA\u30FB\u30D0\u30F3\u30C9\u30EB\u3092\u4F5C\u6210\u3057\u307E\u3059\u3002"
+
+param.signing-key-app.name=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u7F72\u540D\u30AD\u30FC
+param.signing-key-app.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u7F72\u540D\u3059\u308B\u7F72\u540D\u30AD\u30FC\u306E\u30D5\u30EB\u30FB\u30CD\u30FC\u30E0\u3002
+
+param.signing-key-pkg.name=\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u7F72\u540D\u30AD\u30FC
+param.signing-key-pkg.description=PKG\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u3092\u7F72\u540D\u3059\u308B\u7F72\u540D\u30AD\u30FC\u306E\u30D5\u30EB\u30FB\u30CD\u30FC\u30E0\u3002
+
+param.mac-app-store-entitlements.name=\u6A29\u9650\u30D5\u30A1\u30A4\u30EB
+param.mac-app-store-entitlements.description=\u30AB\u30B9\u30BF\u30E0Mac App Store\u6A29\u9650\u30D5\u30A1\u30A4\u30EB\u306E\u30D5\u30A1\u30A4\u30EB\u5834\u6240
+
+param.installer-suffix.name=\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u63A5\u5C3E\u8F9E
+param.installer-suffix.description=\u3053\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u540D\u63A5\u5C3E\u8F9E\u3002<name><suffix>.pkg\u3002
+
+resource.mac-app-store-entitlements=Mac App Store\u6A29\u9650
+resource.mac-app-store-inherit-entitlements=Mac App Store\u7D99\u627F\u6A29\u9650
+
+error.parameters-null=\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u304Cnull\u3067\u3059\u3002
+error.parameters-null.advice=\u975Enull\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u3067\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+error.no-system-runtime=\u30B7\u30B9\u30C6\u30E0JRE\u3092\u4F7F\u7528\u3059\u308B\u3088\u3046\u306B\u69CB\u6210\u3055\u308C\u305F\u30D0\u30F3\u30C9\u30EB
+error.no-system-runtime.advice='runtime'\u3092null\u306B\u8A2D\u5B9A\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\u8A2D\u5B9A\u3057\u306A\u3044\u304B\u3001\u6709\u52B9\u306A\u5024\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.must-sign-app-store=Mac App Store\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306F\u7F72\u540D\u3055\u308C\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u304C\u3001\u7F72\u540D\u306F\u30D0\u30F3\u30C9\u30E9\u69CB\u6210\u306B\u3088\u3063\u3066\u7121\u52B9\u5316\u3055\u308C\u3066\u3044\u307E\u3059\u3002
+error.must-sign-app-store.advice='signBundle'\u3092\u8A2D\u5B9A\u89E3\u9664\u3059\u308B\u304B\u3001'signBundle'\u3092true\u306B\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.no-app-signing-key=Mac App Store\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u7F72\u540D\u30AD\u30FC\u304C\u3042\u308A\u307E\u305B\u3093
+error.no-app-signing-key.advice=XCode\u3092\u4F7F\u7528\u3057\u3066\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u7F72\u540D\u30AD\u30FC\u3092Mac\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306B\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u307E\u3059\u3002
+error.no-pkg-signing-key=Mac App Store\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u306E\u7F72\u540D\u30AD\u30FC\u304C\u3042\u308A\u307E\u305B\u3093
+error.no-pkg-signing-key.advice=XCode\u3092\u4F7F\u7528\u3057\u3066\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u7F72\u540D\u30AD\u30FC\u3092Mac\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306B\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u307E\u3059\u3002
+error.certificate.expired=\u30A8\u30E9\u30FC: \u8A3C\u660E\u66F8\u306F{0}\u306B\u671F\u9650\u304C\u5207\u308C\u307E\u3057\u305F\u3002
+
+
+message.config-save-location=\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C{0}\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B\u306B\u306F\u3053\u308C\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+message.building-bundle={0}\u306EMac App Store\u30D0\u30F3\u30C9\u30EB\u306E\u4F5C\u6210
+mesasge.intermediate-bundle-location=\u4E2D\u9593\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB\u30FB\u30A4\u30E1\u30FC\u30B8: {0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacAppStoreBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,36 @@
+bundler.name=\u652F\u6301 Mac App Store \u7684\u6253\u5305\u7A0B\u5E8F
+bundler.description=\u521B\u5EFA\u53EF\u90E8\u7F72\u5230 Mac App Store \u4E2D\u7684\u4E8C\u8FDB\u5236\u6587\u4EF6\u5305\u3002"
+
+param.signing-key-app.name=\u5E94\u7528\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5
+param.signing-key-app.description=\u7528\u4E8E\u5BF9\u5E94\u7528\u7A0B\u5E8F\u7B7E\u540D\u7684\u7B7E\u540D\u5BC6\u94A5\u7684\u5B8C\u6574\u540D\u79F0\u3002
+
+param.signing-key-pkg.name=\u5B89\u88C5\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5
+param.signing-key-pkg.description=\u7528\u4E8E\u5BF9 PKG \u5B89\u88C5\u7A0B\u5E8F\u7B7E\u540D\u7684\u7B7E\u540D\u5BC6\u94A5\u7684\u5B8C\u6574\u540D\u79F0\u3002
+
+param.mac-app-store-entitlements.name=\u6743\u5229\u6587\u4EF6
+param.mac-app-store-entitlements.description=\u5B9A\u5236 Mac App Store \u6743\u5229\u6587\u4EF6\u7684\u6587\u4EF6\u4F4D\u7F6E
+
+param.installer-suffix.name=\u5B89\u88C5\u7A0B\u5E8F\u540E\u7F00
+param.installer-suffix.description=\u6B64\u7A0B\u5E8F\u5305\u7684\u5B89\u88C5\u6587\u4EF6\u540D\u79F0\u7684\u540E\u7F00\u3002<\u540D\u79F0><\u540E\u7F00>.pkg\u3002
+
+resource.mac-app-store-entitlements=Mac App Store \u6743\u5229
+resource.mac-app-store-inherit-entitlements=Mac App Store \u7EE7\u627F\u6743\u5229
+
+error.parameters-null=\u53C2\u6570\u6620\u5C04\u4E3A\u7A7A\u503C\u3002
+error.parameters-null.advice=\u8BF7\u4F20\u5165\u975E\u7A7A\u53C2\u6570\u6620\u5C04\u3002
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+error.no-system-runtime=\u914D\u7F6E\u4E3A\u4F7F\u7528\u7CFB\u7EDF JRE \u7684\u5305
+error.no-system-runtime.advice=\u4E0D\u8981\u5C06 'runtime' \u8BBE\u7F6E\u4E3A\u7A7A\u503C, \u8981\u4E48\u4E0D\u8BBE\u7F6E\u8BE5\u503C, \u8981\u4E48\u5C06\u5176\u8BBE\u7F6E\u4E3A\u6709\u6548\u503C\u3002
+error.must-sign-app-store=Mac App Store \u5E94\u7528\u7A0B\u5E8F\u5FC5\u987B\u7B7E\u540D, \u800C\u6253\u5305\u7A0B\u5E8F\u914D\u7F6E\u5DF2\u7981\u7528\u7B7E\u540D\u3002
+error.must-sign-app-store.advice=\u53D6\u6D88\u8BBE\u7F6E 'signBundle' \u6216\u8005\u5C06 'signBundle' \u8BBE\u7F6E\u4E3A true\u3002
+error.no-app-signing-key=\u65E0 Mac App Store \u5E94\u7528\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5
+error.no-app-signing-key.advice=\u4F7F\u7528 XCode \u5C06\u5E94\u7528\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5\u5B89\u88C5\u5230 Mac \u5BC6\u94A5\u94FE\u4E2D\u3002
+error.no-pkg-signing-key=\u65E0 Mac App Store \u5B89\u88C5\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5
+error.no-pkg-signing-key.advice=\u4F7F\u7528 XCode \u5C06\u5E94\u7528\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5\u5B89\u88C5\u5230 Mac \u5BC6\u94A5\u94FE\u4E2D\u3002
+error.certificate.expired=\u9519\u8BEF: \u8BC1\u4E66\u5DF2\u5931\u6548 {0}\u3002
+
+
+message.config-save-location=\u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58\u5230 {0}\u3002\u4F7F\u7528\u8FD9\u4E9B\u914D\u7F6E\u6587\u4EF6\u53EF\u5B9A\u5236\u7A0B\u5E8F\u5305\u3002
+message.building-bundle=\u6B63\u5728\u4E3A {0} \u6784\u5EFA Mac App Store \u5305
+mesasge.intermediate-bundle-location=\u4E34\u65F6\u5E94\u7528\u7A0B\u5E8F\u5305\u6620\u50CF: {0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacAppStore_Inherit.entitlements	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://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.packager/macosx/classes/jdk/packager/internal/resources/mac/MacBaseInstallerBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,35 @@
+bundler.name=Mac App Store
+bundler.description=Creates a binary bundle ready for deployment into the Mac App Store.
+
+param.app-bundler.name=Mac App Bundler
+param.app-bundle.description=Creates a .app bundle for the Mac
+
+param.app-image-build-root.name=
+param.app-image-build-root.description=This is temporary location built by the packager that is the root of the image application
+
+param.signing-keychain.name=Signing Keychain
+param.signing-keychain.description=The location of the keychain to use.  If not specified the standard keychains will be used.
+
+param.signing-key-name.name=Signing Key User Name
+param.signing-key-name.description=The user name portion of the typical "Mac Developer ID Application: <user name>" signing key.
+
+param.daemon-bundler.name=Mac Daemon Bundler
+param.daemon-bundler.description=Creates daemon image for the Mac
+
+param.daemon-image-build-root.name=
+param.daemon-image-build-root.description=This is temporary location built by the packager that is the root of the daemon image
+
+param.installer-name.name=Installer Name
+param.installer-name.description=The filename of the generated installer without the file type extension.  Default is <App Name>-<Version>.
+
+param.config-root.name=
+param.config-root.description=
+
+error.parameters-null=Parameters map is null.
+error.parameters-null.advice=Pass in a non-null parameters map.
+
+message.could-not-retrieve-name=Could not retrieve gecos name
+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=When using an external app image you must specify the identifier.
+message.app-image-requires-identifier.advice=Set the identifier via the -appId CLI flag, the fx:application/@id ANT attribute, or via the 'identifier' bundler argument.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacBaseInstallerBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,37 @@
+bundler.name=Mac App Store
+bundler.description=Mac App Store\u3078\u306e\u30c7\u30d7\u30ed\u30a4\u30e1\u30f3\u30c8\u6e96\u5099\u5b8c\u4e86\u306e\u30d0\u30a4\u30ca\u30ea\u30fb\u30d0\u30f3\u30c9\u30eb\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002
+
+param.app-bundler.name=Mac\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30fb\u30d0\u30f3\u30c9\u30e9
+param.app-bundle.description=Mac\u7528\u306e.app\u30d0\u30f3\u30c9\u30eb\u3092\u4f5c\u6210\u3057\u307e\u3059
+
+param.app-image-build-root.name=
+param.app-image-build-root.description=\u3053\u308c\u306f\u30a4\u30e1\u30fc\u30b8\u30fb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30eb\u30fc\u30c8\u3067\u3042\u308b\u30d1\u30c3\u30b1\u30fc\u30b8\u30e3\u306b\u3088\u3063\u3066\u4f5c\u6210\u3055\u308c\u308b\u4e00\u6642\u7684\u306a\u5834\u6240\u3067\u3059
+
+param.signing-keychain.name=\u7f72\u540d\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3
+param.signing-keychain.description=\u4f7f\u7528\u3059\u308b\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3\u306e\u5834\u6240\u3002\u6307\u5b9a\u3055\u308c\u3066\u3044\u306a\u3044\u5834\u5408\u306f\u3001\u6a19\u6e96\u306e\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3\u304c\u4f7f\u7528\u3055\u308c\u307e\u3059\u3002
+
+param.signing-key-name.name=\u7f72\u540d\u30ad\u30fc\u306e\u30e6\u30fc\u30b6\u30fc\u540d
+param.signing-key-name.description=\u4e00\u822c\u7684\u306a"Mac Developer ID\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3: <user name>"\u7f72\u540d\u30ad\u30fc\u306e\u30e6\u30fc\u30b6\u30fc\u540d\u90e8\u5206\u3002
+
+param.daemon-bundler.name=Mac\u30c7\u30fc\u30e2\u30f3\u30fb\u30d0\u30f3\u30c9\u30e9
+param.daemon-bundler.description=Mac\u7528\u306e\u30c7\u30fc\u30e2\u30f3\u30fb\u30a4\u30e1\u30fc\u30b8\u3092\u4f5c\u6210\u3057\u307e\u3059
+
+param.daemon-image-build-root.name=
+param.daemon-image-build-root.description=\u3053\u308c\u306f\u30c7\u30fc\u30e2\u30f3\u30fb\u30a4\u30e1\u30fc\u30b8\u306e\u30eb\u30fc\u30c8\u3067\u3042\u308b\u30d1\u30c3\u30b1\u30fc\u30b8\u30e3\u306b\u3088\u3063\u3066\u4f5c\u6210\u3055\u308c\u308b\u4e00\u6642\u7684\u306a\u5834\u6240\u3067\u3059
+
+param.installer-name.name=\u30a4\u30f3\u30b9\u30c8\u30fc\u30e9\u540d
+param.installer-name.description=\u30d5\u30a1\u30a4\u30eb\u30fb\u30bf\u30a4\u30d7\u62e1\u5f35\u5b50\u306a\u3057\u306e\u751f\u6210\u3055\u308c\u305f\u30a4\u30f3\u30b9\u30c8\uff0d\u30e9\u306e\u30d5\u30a1\u30a4\u30eb\u540d\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u306f<App Name>-<Version>\u3067\u3059\u3002
+
+param.config-root.name=
+param.config-root.description=
+
+error.parameters-null=\u30d1\u30e9\u30e1\u30fc\u30bf\u30fb\u30de\u30c3\u30d7\u304cnull\u3067\u3059\u3002
+error.parameters-null.advice=\u975enull\u30d1\u30e9\u30e1\u30fc\u30bf\u30fb\u30de\u30c3\u30d7\u3067\u6e21\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+
+message.app-image-dir-does-not-exist=\u6307\u5b9a\u3055\u308c\u305f\u30a4\u30e1\u30fc\u30b8\u30fb\u30c7\u30a3\u30ec\u30af\u30c8\u30ea {0}: {1}\u306f\u5b58\u5728\u3057\u307e\u305b\u3093
+message.app-image-dir-does-not-exist.advice={0}\u306e\u5024\u304c\u5b58\u5728\u3059\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044
+message.could-not-retrieve-name=gecos\u540d\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f
+message.app-image-requires-app-name=\u5916\u90e8\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30fb\u30a4\u30e1\u30fc\u30b8\u3092\u4f7f\u7528\u3059\u308b\u5834\u5408\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u540d\u3092\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002
+message.app-image-requires-app-name.advice=-name CLI\u30d5\u30e9\u30b0\u3001fx:application/@name ANT\u5c5e\u6027\u307e\u305f\u306f'appName'\u30d0\u30f3\u30c9\u30e9\u5f15\u6570\u3067\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u540d\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002
+message.app-image-requires-identifier=\u5916\u90e8\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30fb\u30a4\u30e1\u30fc\u30b8\u3092\u4f7f\u7528\u3059\u308b\u5834\u5408\u3001\u8b58\u5225\u5b50\u3092\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002
+message.app-image-requires-identifier.advice=-appId CLI\u30d5\u30e9\u30b0\u3001fx:application/@id ANT\u5c5e\u6027\u307e\u305f\u306f'identifier'\u30d0\u30f3\u30c9\u30e9\u5f15\u6570\u3067\u8b58\u5225\u5b50\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacBaseInstallerBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,37 @@
+bundler.name=Mac App Store
+bundler.description=\u521b\u5efa\u53ef\u90e8\u7f72\u5230 Mac App Store \u4e2d\u7684\u4e8c\u8fdb\u5236\u6587\u4ef6\u5305\u3002
+
+param.app-bundler.name=Mac \u5e94\u7528\u7a0b\u5e8f\u6253\u5305\u7a0b\u5e8f
+param.app-bundle.description=\u521b\u5efa\u7528\u4e8e Mac \u7684 .app \u5305
+
+param.app-image-build-root.name=
+param.app-image-build-root.description=\u8fd9\u662f\u7531\u6253\u5305\u7a0b\u5e8f\u6784\u5efa\u7684\u4e34\u65f6\u4f4d\u7f6e, \u662f\u6620\u50cf\u5e94\u7528\u7a0b\u5e8f\u7684\u6839\u76ee\u5f55
+
+param.signing-keychain.name=\u7b7e\u540d\u5bc6\u94a5\u94fe
+param.signing-keychain.description=\u8981\u4f7f\u7528\u7684\u5bc6\u94a5\u94fe\u7684\u4f4d\u7f6e\u3002\u5982\u679c\u672a\u6307\u5b9a, \u5219\u5c06\u4f7f\u7528\u6807\u51c6\u5bc6\u94a5\u94fe\u3002
+
+param.signing-key-name.name=\u7b7e\u540d\u5bc6\u94a5\u7528\u6237\u540d
+param.signing-key-name.description=\u5178\u578b "Mac \u5f00\u53d1\u8005 ID \u5e94\u7528\u7a0b\u5e8f: <\u7528\u6237\u540d>" \u7b7e\u540d\u5bc6\u94a5\u7684\u7528\u6237\u540d\u90e8\u5206\u3002
+
+param.daemon-bundler.name=Mac \u5b88\u62a4\u7a0b\u5e8f\u6253\u5305\u7a0b\u5e8f
+param.daemon-bundler.description=\u521b\u5efa\u7528\u4e8e Mac \u7684\u5b88\u62a4\u7a0b\u5e8f\u6620\u50cf
+
+param.daemon-image-build-root.name=
+param.daemon-image-build-root.description=\u8fd9\u662f\u7531\u6253\u5305\u7a0b\u5e8f\u6784\u5efa\u7684\u4e34\u65f6\u4f4d\u7f6e, \u662f\u5b88\u62a4\u7a0b\u5e8f\u6620\u50cf\u7684\u6839\u76ee\u5f55
+
+param.installer-name.name=\u5b89\u88c5\u7a0b\u5e8f\u540d\u79f0
+param.installer-name.description=\u6240\u751f\u6210\u5b89\u88c5\u7a0b\u5e8f\u4e0d\u5e26\u6587\u4ef6\u7c7b\u578b\u6269\u5c55\u540d\u7684\u6587\u4ef6\u540d\u3002\u9ed8\u8ba4\u503c\u4e3a <\u5e94\u7528\u7a0b\u5e8f\u540d\u79f0>-<\u7248\u672c>\u3002
+
+param.config-root.name=
+param.config-root.description=
+
+error.parameters-null=\u53c2\u6570\u6620\u5c04\u4e3a\u7a7a\u503c\u3002
+error.parameters-null.advice=\u8bf7\u4f20\u5165\u975e\u7a7a\u53c2\u6570\u6620\u5c04\u3002
+
+message.app-image-dir-does-not-exist=\u6307\u5b9a\u7684\u6620\u50cf\u76ee\u5f55 {0}: {1} \u4e0d\u5b58\u5728
+message.app-image-dir-does-not-exist.advice=\u786e\u8ba4 {0} \u7684\u503c\u662f\u5426\u5b58\u5728
+message.could-not-retrieve-name=\u65e0\u6cd5\u68c0\u7d22 gecos \u540d\u79f0
+message.app-image-requires-app-name=\u4f7f\u7528\u5916\u90e8\u5e94\u7528\u7a0b\u5e8f\u6620\u50cf\u65f6, \u5fc5\u987b\u6307\u5b9a\u5e94\u7528\u7a0b\u5e8f\u540d\u79f0\u3002
+message.app-image-requires-app-name.advice=\u901a\u8fc7 -name CLI \u6807\u8bb0, fx:application/@name ANT \u5c5e\u6027\u6216\u901a\u8fc7 'appName' \u6253\u5305\u7a0b\u5e8f\u53c2\u6570\u8bbe\u7f6e\u5e94\u7528\u7a0b\u5e8f\u540d\u79f0\u3002
+message.app-image-requires-identifier=\u4f7f\u7528\u5916\u90e8\u5e94\u7528\u7a0b\u5e8f\u6620\u50cf\u65f6, \u5fc5\u987b\u6307\u5b9a\u6807\u8bc6\u7b26\u3002
+message.app-image-requires-identifier.advice=\u901a\u8fc7 -appId CLI \u6807\u8bb0, fx:application/@id ANT \u5c5e\u6027\u6216\u901a\u8fc7 'identifier' \u6253\u5305\u7a0b\u5e8f\u53c2\u6570\u8bbe\u7f6e\u6807\u8bc6\u7b26\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacDmgBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,36 @@
+bundler.name=DMG Installer
+bundler.description=Mac DMG Installer Bundle
+
+param.simple-dmg.name=Simple DMG Generation
+param.simple-dmg.description=Generate a DMG without AppleScript customizations.  Recommended for continuous automated builds.
+
+param.installer-suffix.name=Installer Suffix
+param.installer-suffix.description=The suffix for the installer name for this package.  <name><suffix>.dmg.
+
+error.parameters-null=Parameters map is null.
+error.parameters-null.advice=Pass in a non-null parameters map.
+
+error.dmg-does-not-do-daemons=DMG bundler doesn't support services.
+error.dmg-does-not-do-daemons.advice=Make sure that the service hint is set to false.
+
+error.license-missing=Specified license file is missing.
+error.license-missing.advice=Make sure that "{0}" references a file in the app resources, and that it is relative file reference.
+
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+
+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
+
+message.building-dmg=Building DMG package for {0}
+message.running-script=Running shell script on application image [{0}]
+message.intermediate-image-location=[DEBUG] Intermediate application bundle image\: {0}
+message.config-save-location=Config files are saved to {0}. Use them to customize package.
+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}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacDmgBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,36 @@
+bundler.name=DMG\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9
+bundler.description=Mac DMG\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FB\u30D0\u30F3\u30C9\u30EB
+
+param.simple-dmg.name=DMG\u306E\u7C21\u6613\u751F\u6210
+param.simple-dmg.description=AppleScript\u306E\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u306A\u3057\u3067DMG\u3092\u751F\u6210\u3057\u307E\u3059\u3002\u9023\u7D9A\u3057\u305F\u81EA\u52D5\u4F5C\u6210\u306E\u5834\u5408\u306B\u304A\u85A6\u3081\u3057\u307E\u3059\u3002
+
+param.installer-suffix.name=\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u63A5\u5C3E\u8F9E
+param.installer-suffix.description=\u3053\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u540D\u306E\u63A5\u5C3E\u8F9E\u3002<name><suffix>.dmg\u3002
+
+error.parameters-null=\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u304Cnull\u3067\u3059\u3002
+error.parameters-null.advice=\u975Enull\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u3067\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.dmg-does-not-do-daemons=DMG\u30D0\u30F3\u30C9\u30E9\u306F\u30B5\u30FC\u30D3\u30B9\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3066\u3044\u307E\u305B\u3093\u3002
+error.dmg-does-not-do-daemons.advice=\u30B5\u30FC\u30D3\u30B9\u306E\u30D2\u30F3\u30C8\u304Cfalse\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.license-missing=\u6307\u5B9A\u3057\u305F\u30E9\u30A4\u30BB\u30F3\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\u3002
+error.license-missing.advice="{0}"\u304C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30EA\u30BD\u30FC\u30B9\u5185\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u53C2\u7167\u3057\u3001\u76F8\u5BFE\u30D5\u30A1\u30A4\u30EB\u53C2\u7167\u3067\u3042\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+
+resource.dmg-setup-script=DMG\u8A2D\u5B9A\u30B9\u30AF\u30EA\u30D7\u30C8
+resource.license-setup=\u30E9\u30A4\u30BB\u30F3\u30B9\u306E\u8A2D\u5B9A
+resource.dmg-background=dmg\u80CC\u666F
+resource.volume-icon=\u30DC\u30EA\u30E5\u30FC\u30E0\u30FB\u30A2\u30A4\u30B3\u30F3
+resource.post-install-script=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u3092\u79FB\u5165\u3057\u305F\u5F8C\u306B\u5B9F\u884C\u3059\u308B\u30B9\u30AF\u30EA\u30D7\u30C8
+
+message.building-dmg={0}\u306EDMG\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059
+message.running-script=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8[{0}]\u3067\u30B7\u30A7\u30EB\u30FB\u30B9\u30AF\u30EA\u30D7\u30C8\u3092\u5B9F\u884C\u3057\u3066\u3044\u307E\u3059
+message.intermediate-image-location=[\u30C7\u30D0\u30C3\u30B0]\u4E2D\u9593\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB\u30FB\u30A4\u30E1\u30FC\u30B8: {0}
+message.config-save-location=\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C{0}\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B\u306B\u306F\u3053\u308C\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+message.preparing-dmg-setup=dmg\u306E\u8A2D\u5B9A\u3092\u6E96\u5099\u3057\u3066\u3044\u307E\u3059: {0}
+message.creating-dmg-file=DMG\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059: {0}
+message.dmg-cannot-be-overwritten=Dmg\u30D5\u30A1\u30A4\u30EB\u306F\u5B58\u5728\u3057({0}\u3001\u524A\u9664\u3067\u304D\u307E\u305B\u3093\u3002
+message.output-to-location={0}\u306E\u7D50\u679C\u306EDMG\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9: {1}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacDmgBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,36 @@
+bundler.name=DMG \u5B89\u88C5\u7A0B\u5E8F
+bundler.description=Mac DMG \u5B89\u88C5\u7A0B\u5E8F\u5305
+
+param.simple-dmg.name=\u7B80\u5355 DMG \u751F\u6210
+param.simple-dmg.description=\u751F\u6210\u4E0D\u5E26 AppleScript \u5B9A\u5236\u7684 DMG\u3002\u5EFA\u8BAE\u7528\u4E8E\u8FDE\u7EED\u81EA\u52A8\u6784\u5EFA\u3002
+
+param.installer-suffix.name=\u5B89\u88C5\u7A0B\u5E8F\u540E\u7F00
+param.installer-suffix.description=\u6B64\u7A0B\u5E8F\u5305\u7684\u5B89\u88C5\u6587\u4EF6\u540D\u79F0\u7684\u540E\u7F00\u3002<\u540D\u79F0><\u540E\u7F00>.dmg\u3002
+
+error.parameters-null=\u53C2\u6570\u6620\u5C04\u4E3A\u7A7A\u503C\u3002
+error.parameters-null.advice=\u8BF7\u4F20\u5165\u975E\u7A7A\u53C2\u6570\u6620\u5C04\u3002
+
+error.dmg-does-not-do-daemons=DMG \u6253\u5305\u7A0B\u5E8F\u4E0D\u652F\u6301\u670D\u52A1\u3002
+error.dmg-does-not-do-daemons.advice=\u786E\u4FDD\u670D\u52A1\u63D0\u793A\u8BBE\u7F6E\u4E3A false\u3002
+
+error.license-missing=\u7F3A\u5C11\u6307\u5B9A\u7684\u8BB8\u53EF\u8BC1\u6587\u4EF6\u3002
+error.license-missing.advice=\u786E\u4FDD "{0}" \u5F15\u7528\u5E94\u7528\u7A0B\u5E8F\u8D44\u6E90\u4E2D\u7684\u6587\u4EF6, \u5E76\u4E14\u662F\u76F8\u5BF9\u6587\u4EF6\u5F15\u7528\u3002
+
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+
+resource.dmg-setup-script=DMG \u8BBE\u7F6E\u811A\u672C
+resource.license-setup=\u8BB8\u53EF\u8BC1\u8BBE\u7F6E
+resource.dmg-background=dmg \u80CC\u666F
+resource.volume-icon=\u5377\u56FE\u6807
+resource.post-install-script=\u8981\u5728\u586B\u5145\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\u4E4B\u540E\u8FD0\u884C\u7684\u811A\u672C
+
+message.building-dmg=\u6B63\u5728\u4E3A {0} \u6784\u5EFA DMG \u7A0B\u5E8F\u5305
+message.running-script=\u6B63\u5728\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF [{0}] \u4E0A\u8FD0\u884C shell \u811A\u672C
+message.intermediate-image-location=[\u8C03\u8BD5] \u4E34\u65F6\u5E94\u7528\u7A0B\u5E8F\u5305\u6620\u50CF: {0}
+message.config-save-location=\u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58\u5230 {0}\u3002\u4F7F\u7528\u8FD9\u4E9B\u914D\u7F6E\u6587\u4EF6\u53EF\u5B9A\u5236\u7A0B\u5E8F\u5305\u3002
+message.preparing-dmg-setup=\u6B63\u5728\u51C6\u5907 dmg \u8BBE\u7F6E: {0}
+message.creating-dmg-file=\u6B63\u5728\u521B\u5EFA DMG \u6587\u4EF6: {0}
+message.dmg-cannot-be-overwritten=Dmg \u6587\u4EF6\u5DF2\u5B58\u5728 ({0}) \u4E14\u65E0\u6CD5\u5220\u9664\u3002
+message.output-to-location=\u4E3A {0} \u751F\u6210\u7684 DMG \u5B89\u88C5\u7A0B\u5E8F: {1}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacPkgBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,39 @@
+bundler.name=PKG Installer
+bundler.description=Mac PKG Installer Bundle.
+
+param.signing-key-developer-id-installer.name=Apple Developer ID Installer Signing Key
+param.signing-key-developer-id-installer.description=The full name of the Apple Developer ID Installer signing key.
+
+param.packages-root.name=
+param.packages-root.description=This is temporary location for component packages (application and daemon).  The packages are incorporated into final product package.
+
+param.installer-suffix.name=Installer Suffix
+param.installer-suffix.description=The suffix for the installer name for this package.  <name><suffix>.pkg.
+
+param.scripts-dir.name=
+param.scripts-dir.description=This is temporary location for package scripts
+
+param.mac-install-dir.name=Mac Installation Directory
+param.mac-install-dir.description=Installation directory of the application on Mac.
+
+resource.pkg-preinstall-script=PKG preinstall script
+resource.pkg-postinstall-script=PKG postinstall script
+resource.pkg-background-image=pkg background image
+resource.post-install-script=script to run after application image is populated
+
+error.parameters-null=Parameters map is null.
+error.parameters-null.advice=Pass in a non-null parameters map.
+error.license-missing=Specified license file is missing.
+error.license-missing.advice=Make sure that "{0}" references a file in the app resources, and that it is relative to the basedir "{1}".
+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-installer' or unset 'signBundle' or set 'signBundle' to false.
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+
+message.building-pkg=Building PKG package for {0}
+message.running-script=Running shell script on application image [{0}]
+message.preparing-scripts=Preparing package scripts
+message.preparing-distribution-dist=Preparing distribution.dist\: {0}
+message.config-save-location=Config files are saved to {0}. Use them to customize package.
+message.intermediate-image-location=[DEBUG] Intermediate application bundle image\: {0}
+message.signing.pkg=Warning: For signing PKG, you might need to set "Always Trust" for your certificate using "Keychain Access" tool.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacPkgBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,35 @@
+bundler.name=PKG\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9
+bundler.description=Mac PKG\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FB\u30D0\u30F3\u30C9\u30EB\u3002
+
+param.signing-key-developer-id-installer.name=Apple Developer ID\u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u7F72\u540D\u30AD\u30FC
+param.signing-key-developer-id-installer.description=Apple Developer ID\u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u7F72\u540D\u30AD\u30FC\u306E\u30D5\u30EB\u30FB\u30CD\u30FC\u30E0\u3002
+
+param.packages-root.name=
+param.packages-root.description=\u3053\u308C\u306F\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8(\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u304A\u3088\u3073\u30C7\u30FC\u30E2\u30F3)\u306E\u4E00\u6642\u7684\u306A\u5834\u6240\u3067\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u306F\u6700\u7D42\u88FD\u54C1\u30D1\u30C3\u30B1\u30FC\u30B8\u306B\u7D44\u307F\u8FBC\u307E\u308C\u307E\u3059\u3002
+
+param.installer-suffix.name=\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u63A5\u5C3E\u8F9E
+param.installer-suffix.description=\u3053\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u540D\u63A5\u5C3E\u8F9E\u3002<name><suffix>.pkg\u3002
+
+param.scripts-dir.name=
+param.scripts-dir.description=\u3053\u308C\u306F\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30B9\u30AF\u30EA\u30D7\u30C8\u306E\u4E00\u6642\u7684\u306A\u5834\u6240\u3067\u3059
+
+resource.pkg-preinstall-script=PKG\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u524D\u30B9\u30AF\u30EA\u30D7\u30C8
+resource.pkg-postinstall-script=PKG\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u5F8C\u30B9\u30AF\u30EA\u30D7\u30C8
+resource.pkg-background-image=pkg\u80CC\u666F\u30A4\u30E1\u30FC\u30B8
+resource.post-install-script=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u3092\u79FB\u5165\u3057\u305F\u5F8C\u306B\u5B9F\u884C\u3059\u308B\u30B9\u30AF\u30EA\u30D7\u30C8
+
+error.parameters-null=\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u304Cnull\u3067\u3059\u3002
+error.parameters-null.advice=\u975Enull\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u3067\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.license-missing=\u6307\u5B9A\u3057\u305F\u30E9\u30A4\u30BB\u30F3\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\u3002
+error.license-missing.advice="{0}"\u304C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30EA\u30BD\u30FC\u30B9\u5185\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u53C2\u7167\u3057\u3001\u30D9\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA"{1}"\u306B\u5BFE\u3057\u3066\u76F8\u5BFE\u7684\u3067\u3042\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.explicit-sign-no-cert=\u7F72\u540D\u304C\u660E\u793A\u7684\u306B\u8981\u6C42\u3055\u308C\u307E\u3057\u305F\u304C\u3001\u7F72\u540D\u8A3C\u660E\u66F8\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002
+error.explicit-sign-no-cert.advice=\u6709\u52B9\u306A\u8A3C\u660E\u66F8\u3092'mac.signing-key-developer-id-installer'\u3067\u6307\u5B9A\u3059\u308B\u304B\u3001'signBundle'\u3092\u8A2D\u5B9A\u89E3\u9664\u3059\u308B\u304B\u3001\u307E\u305F\u306F'signBundle'\u3092false\u306B\u8A2D\u5B9A\u3057\u307E\u3059\u3002
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+
+message.building-pkg={0}\u306EPKG\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059
+message.running-script=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8[{0}]\u3067\u30B7\u30A7\u30EB\u30FB\u30B9\u30AF\u30EA\u30D7\u30C8\u3092\u5B9F\u884C\u3057\u3066\u3044\u307E\u3059
+message.preparing-scripts=\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30B9\u30AF\u30EA\u30D7\u30C8\u3092\u6E96\u5099\u3057\u3066\u3044\u307E\u3059
+message.preparing-distribution-dist=distribution.dist\u3092\u6E96\u5099\u3057\u3066\u3044\u307E\u3059: {0}
+message.config-save-location=\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C{0}\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B\u306B\u306F\u3053\u308C\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+message.intermediate-image-location=[\u30C7\u30D0\u30C3\u30B0]\u4E2D\u9593\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB\u30FB\u30A4\u30E1\u30FC\u30B8: {0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacPkgBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,35 @@
+bundler.name=PKG \u5B89\u88C5\u7A0B\u5E8F
+bundler.description=Mac PKG \u5B89\u88C5\u7A0B\u5E8F\u5305\u3002
+
+param.signing-key-developer-id-installer.name=Apple \u5F00\u53D1\u8005 ID \u5B89\u88C5\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5
+param.signing-key-developer-id-installer.description=Apple \u5F00\u53D1\u8005 ID \u5B89\u88C5\u7A0B\u5E8F\u7B7E\u540D\u5BC6\u94A5\u7684\u5168\u540D\u3002
+
+param.packages-root.name=
+param.packages-root.description=\u8FD9\u662F\u7EC4\u4EF6\u7A0B\u5E8F\u5305 (\u5E94\u7528\u7A0B\u5E8F\u548C\u5B88\u62A4\u7A0B\u5E8F) \u7684\u4E34\u65F6\u4F4D\u7F6E\u3002\u7A0B\u5E8F\u5305\u96C6\u6210\u5230\u6700\u7EC8\u4EA7\u54C1\u7A0B\u5E8F\u5305\u4E2D\u3002
+
+param.installer-suffix.name=\u5B89\u88C5\u7A0B\u5E8F\u540E\u7F00
+param.installer-suffix.description=\u6B64\u7A0B\u5E8F\u5305\u7684\u5B89\u88C5\u6587\u4EF6\u540D\u79F0\u7684\u540E\u7F00\u3002<\u540D\u79F0><\u540E\u7F00>.pkg\u3002
+
+param.scripts-dir.name=
+param.scripts-dir.description=\u8FD9\u662F\u7A0B\u5E8F\u5305\u811A\u672C\u7684\u4E34\u65F6\u4F4D\u7F6E
+
+resource.pkg-preinstall-script=PKG \u5B89\u88C5\u524D\u811A\u672C
+resource.pkg-postinstall-script=PKG \u5B89\u88C5\u540E\u811A\u672C
+resource.pkg-background-image=pkg \u80CC\u666F\u56FE\u50CF
+resource.post-install-script=\u8981\u5728\u586B\u5145\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\u4E4B\u540E\u8FD0\u884C\u7684\u811A\u672C
+
+error.parameters-null=\u53C2\u6570\u6620\u5C04\u4E3A\u7A7A\u503C\u3002
+error.parameters-null.advice=\u8BF7\u4F20\u5165\u975E\u7A7A\u53C2\u6570\u6620\u5C04\u3002
+error.license-missing=\u7F3A\u5C11\u6307\u5B9A\u7684\u8BB8\u53EF\u8BC1\u6587\u4EF6\u3002
+error.license-missing.advice=\u8BF7\u786E\u4FDD "{0}" \u5F15\u7528\u5E94\u7528\u7A0B\u5E8F\u8D44\u6E90\u4E2D\u7684\u6587\u4EF6, \u5E76\u4E14\u4F7F\u7528\u57FA\u76EE\u5F55 "{1}" \u7684\u76F8\u5BF9\u76EE\u5F55\u3002
+error.explicit-sign-no-cert=\u5DF2\u660E\u786E\u8BF7\u6C42\u7B7E\u540D, \u4F46\u672A\u6307\u5B9A\u7B7E\u540D\u8BC1\u4E66\u3002
+error.explicit-sign-no-cert.advice=\u5728 'mac.signing-key-developer-id-installer' \u4E2D\u6307\u5B9A\u6709\u6548\u7684\u8BC1\u4E66, \u6216\u8005\u53D6\u6D88\u8BBE\u7F6E 'signBundle', \u6216\u8005\u5C06 'signBundle' \u8BBE\u7F6E\u4E3A false\u3002
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+
+message.building-pkg=\u6B63\u5728\u4E3A {0} \u6784\u5EFA PKG \u7A0B\u5E8F\u5305
+message.running-script=\u6B63\u5728\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF [{0}] \u4E0A\u8FD0\u884C shell \u811A\u672C
+message.preparing-scripts=\u6B63\u5728\u51C6\u5907\u7A0B\u5E8F\u5305\u811A\u672C
+message.preparing-distribution-dist=\u6B63\u5728\u51C6\u5907 distribution.dist: {0}
+message.config-save-location=\u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58\u5230 {0}\u3002\u4F7F\u7528\u8FD9\u4E9B\u914D\u7F6E\u6587\u4EF6\u53EF\u5B9A\u5236\u7A0B\u5E8F\u5305\u3002
+message.intermediate-image-location=[\u8C03\u8BD5] \u4E34\u65F6\u5E94\u7528\u7A0B\u5E8F\u5305\u6620\u50CF: {0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/MacResources.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, 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.packager.internal.resources.mac;
+
+// no-op, use as anchor for resource loading
+public class MacResources {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/Runtime-Info.plist.template	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://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.packager/macosx/classes/jdk/packager/internal/resources/mac/background_dmg.png has changed
Binary file src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/background_pkg.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/launchd.plist.template	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>Label</key>
+    <string>DEPLOY_DAEMON_IDENTIFIER</string>
+    <key>ProgramArguments</key>
+    <array>
+        <string>DEPLOY_DAEMON_LAUNCHER_PATH</string>
+    </array>
+    <key>RunAtLoad</key><DEPLOY_RUN_AT_LOAD/>
+    <key>KeepAlive</key><DEPLOY_KEEP_ALIVE/>
+</dict>
+</plist>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/lic_template.plist	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://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.packager/macosx/classes/jdk/packager/internal/resources/mac/postinstall.template	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,6 @@
+#!/usr/bin/env sh
+
+set -e
+launchctl load "/Library/LaunchDaemons/DEPLOY_LAUNCHD_PLIST_FILE"
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/jdk/packager/internal/resources/mac/preinstall.template	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,8 @@
+#!/usr/bin/env sh
+
+set -e
+if launchctl list "DEPLOY_DAEMON_IDENTIFIER" &> /dev/null; then
+    launchctl unload "/Library/LaunchDaemons/DEPLOY_LAUNCHD_PLIST_FILE"
+fi
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/classes/module-info.java.extra	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 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.
+ */
+
+
+provides jdk.packager.internal.Bundler with
+    jdk.packager.internal.mac.MacAppBundler,
+    jdk.packager.internal.mac.MacAppStoreBundler,
+    jdk.packager.internal.mac.MacDmgBundler,
+    jdk.packager.internal.mac.MacPkgBundler;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/macosx/native/launcher/main.m	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+#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/libpackager.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(argc, argv) == true) {
+                result = 0;
+
+                if (stop != NULL) {
+                    stop();
+                }
+            }
+
+            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.packager/macosx/native/library/MacPlatform.mm	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+
+#ifdef MAC
+
+#include "MacPlatform.h"
+#include "Helpers.h"
+#include "Package.h"
+#include "PropertyFile.h"
+#include "IniFile.h"
+
+#include <sys/sysctl.h>
+#include <pthread.h>
+#include <vector>
+
+#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_PACKAGER_TMP_DIR "/Library/Application Support/Oracle/Java/Packager/tmp"
+
+//--------------------------------------------------------------------------------------------------
+
+NSString* StringToNSString(TString Value) {
+    NSString* result = [NSString stringWithCString:Value.c_str()
+                                          encoding:[NSString defaultCStringEncoding]];
+    return result;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+MacPlatform::MacPlatform(void) : Platform(), GenericPlatform(), PosixPlatform() {
+}
+
+MacPlatform::~MacPlatform(void) {
+}
+
+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_PACKAGER_TMP_DIR);
+}
+
+void MacPlatform::reactivateAnotherInstance() {
+    if (singleInstanceProcessId == 0) {
+        printf("Unable to reactivate another instance, PID is undefined");
+        return;
+    }
+    NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier: singleInstanceProcessId];
+    if (app != nil) {
+        [app activateWithOptions: NSApplicationActivateIgnoringOtherApps];
+    } else {
+        printf("Unable to reactivate another instance PID: %d", singleInstanceProcessId);
+    }
+}
+
+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 (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 (CFStringGetCString(StringRef, result, maxSize, kCFStringEncodingUTF8) == true) {
+                    release = true;
+                }
+                else {
+                    delete[] result;
+                    result = NULL;
+                }
+            }
+        }
+        @finally {
+            CFRelease(StringRef);
+        }
+    }
+
+    return result;
+}
+
+void MacPlatform::SetCurrentDirectory(TString Value) {
+    chdir(PlatformString(Value).toPlatformString());
+}
+
+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::GetBundledJVMLibraryFileName(TString RuntimePath) {
+    TString result;
+
+    result = FilePath::IncludeTrailingSeparater(RuntimePath) + _T("Contents/Home/jre/lib/jli/libjli.dylib");
+
+    if (FilePath::FileExists(result) == false) {
+        result = FilePath::IncludeTrailingSeparater(RuntimePath) + _T("Contents/Home/lib/jli/libjli.dylib");
+
+        if (FilePath::FileExists(result) == false) {
+            result = _T("");
+        }
+    }
+
+    return result;
+}
+
+TString MacPlatform::GetAppName() {
+    NSString *appName = [[NSProcessInfo processInfo] processName];
+    TString result = [appName UTF8String];
+    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 packager uses unless
+// a packager config file exists.
+ISectionalPropertyContainer* MacPlatform::GetConfigFile(TString FileName) {
+    IniFile* result = new IniFile();
+
+    if (UsePListForConfigFile() == false) {
+        if (result->LoadFromFile(FileName) == false) {
+            // New property file format was not found, attempt to load old property file format.
+            Helpers::LoadOldConfigFile(FileName, result);
+        }
+    }
+    else {
+        NSBundle *mainBundle = [NSBundle mainBundle];
+        NSDictionary *infoDictionary = [mainBundle infoDictionary];
+        std::map<TString, TString> keys = GetKeys();
+
+        // Packager options.
+        AppendPListDictionaryToIniFile(infoDictionary, result, keys[CONFIG_SECTION_APPLICATION], false);
+
+        // jvmargs
+        AppendPListArrayToIniFile(infoDictionary, result, keys[CONFIG_SECTION_JVMOPTIONS]);
+
+        // jvmuserargs
+        AppendPListDictionaryToIniFile(infoDictionary, result, keys[CONFIG_SECTION_JVMUSEROPTIONS]);
+
+        // Generate AppCDS Cache
+        AppendPListDictionaryToIniFile(infoDictionary, result, keys[CONFIG_SECTION_APPCDSJVMOPTIONS]);
+        AppendPListDictionaryToIniFile(infoDictionary, result, keys[CONFIG_SECTION_APPCDSGENERATECACHEJVMOPTIONS]);
+
+        // 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);
+}
+
+#include <mach-o/dyld.h>
+
+TString MacPlatform::GetModuleFileName() {
+    //return GetModuleFileNameOSX();
+
+    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];
+    TPlatformNumber result = memory / 1048576; // Convert from bytes to megabytes.
+    return result;
+}
+
+std::map<TString, TString> MacPlatform::GetKeys() {
+    std::map<TString, TString> keys;
+
+    if (UsePListForConfigFile() == false) {
+        return GenericPlatform::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("JVMMainJarName")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINMODULE_KEY,     _T("JVMMainModuleName")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINCLASSNAME_KEY,  _T("JVMMainClassName")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_CLASSPATH_KEY,      _T("JVMAppClasspath")));
+        keys.insert(std::map<TString, TString>::value_type(APP_NAME_KEY,              _T("CFBundleName")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_ID_KEY,         _T("JVMPreferencesID")));
+        keys.insert(std::map<TString, TString>::value_type(JVM_RUNTIME_KEY,           _T("JVMRuntime")));
+        keys.insert(std::map<TString, TString>::value_type(PACKAGER_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_JVMOPTIONS,     _T("JVMOptions")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_JVMUSEROPTIONS, _T("JVMUserOptions")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS, _T("JVMUserOverrideOptions")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_APPCDSJVMOPTIONS, _T("AppCDSJVMOptions")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_APPCDSGENERATECACHEJVMOPTIONS, _T("AppCDSGenerateCacheJVMOptions")));
+        keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_ARGOPTIONS,     _T("ArgOptions")));
+    }
+
+    return keys;
+}
+
+#ifdef DEBUG
+bool MacPlatform::IsNativeDebuggerPresent() {
+    int state;
+    int mib[4];
+    struct kinfo_proc info;
+    size_t size;
+
+    info.kp_proc.p_flag = 0;
+
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_PROC;
+    mib[2] = KERN_PROC_PID;
+    mib[3] = getpid();
+
+    size = sizeof(info);
+    state = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
+    assert(state == 0);
+    return ((info.kp_proc.p_flag & P_TRACED) != 0);
+}
+
+int MacPlatform::GetProcessID() {
+    int pid = [[NSProcessInfo processInfo] processIdentifier];
+    return pid;
+}
+#endif //DEBUG
+
+//--------------------------------------------------------------------------------------------------
+
+class UserDefaults {
+private:
+    OrderedMap<TString, TString> FData;
+    TString FDomainName;
+
+    bool ReadDictionary(NSDictionary *Items, OrderedMap<TString, TString> &Data) {
+        bool result = false;
+
+        for (id key in Items) {
+            id option = [Items valueForKey:key];
+
+            if ([key isKindOfClass:[NSString class]] && [option isKindOfClass:[NSString class]]) {
+                TString name = [key UTF8String];
+                TString value = [option UTF8String];
+
+                if (name.empty() == false) {
+                    Data.Append(name, value);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    // Open and read the defaults file specified by domain.
+    bool ReadPreferences(NSDictionary *Defaults, std::list<TString> Keys, OrderedMap<TString, TString> &Data) {
+        bool result = false;
+
+        if (Keys.size() > 0 && Defaults != NULL) {
+            NSDictionary *node = Defaults;
+
+            while (Keys.size() > 0 && node != NULL) {
+                TString key = Keys.front();
+                Keys.pop_front();
+                NSString *tempKey = StringToNSString(key);
+                node = [node valueForKey:tempKey];
+
+                if (Keys.size() == 0) {
+                    break;
+                }
+            }
+
+            if (node != NULL) {
+                result = ReadDictionary(node, Data);
+            }
+        }
+
+        return result;
+    }
+
+    NSDictionary* LoadPreferences(TString DomainName) {
+        NSDictionary *result = NULL;
+
+        if (DomainName.empty() == false) {
+            NSUserDefaults *prefs = [[NSUserDefaults alloc] init];
+
+            if (prefs != NULL) {
+                NSString *lDomainName = StringToNSString(DomainName);
+                result = [prefs persistentDomainForName: lDomainName];
+            }
+        }
+
+        return result;
+    }
+
+public:
+    UserDefaults(TString DomainName) {
+        FDomainName = DomainName;
+    }
+
+    bool Read(std::list<TString> Keys) {
+        NSDictionary *defaults = LoadPreferences(FDomainName);
+        return ReadPreferences(defaults, Keys, FData);
+    }
+
+    OrderedMap<TString, TString> GetData() {
+        return FData;
+    }
+};
+
+//--------------------------------------------------------------------------------------------------
+
+MacJavaUserPreferences::MacJavaUserPreferences(void) : JavaUserPreferences() {
+}
+
+TString toLowerCase(TString Value) {
+    // Use Cocoa's lowercase method because it is better than the ones provided by C/C++.
+    NSString *temp = StringToNSString(Value);
+    temp = [temp lowercaseString];
+    TString result = [temp UTF8String];
+    return result;
+}
+
+// Split the string Value into using Delimiter.
+std::list<TString> Split(TString Value, TString Delimiter) {
+    std::list<TString> result;
+    std::vector<char> buffer(Value.c_str(), Value.c_str() + Value.size() + 1);
+    char *p = strtok(&buffer[0], Delimiter.data());
+
+    while (p != NULL) {
+        TString token = p;
+        result.push_back(token);
+        p = strtok(NULL, Delimiter.data());
+    }
+
+    return result;
+}
+
+// 1. If the path is fewer than three components (Example: one/two/three) then the domain is the
+//    default domain "com.apple.java.util.prefs" stored in the plist file
+//    ~/Library/Preferences/com.apple.java.util.prefs.plist
+//
+//    For example: If AppID = "hello", the path is "hello/JVMUserOptions and the
+//    plist file is ~/Library/Preferences/com.apple.java.util.prefs.plist containing the contents:
+//
+//    <?xml version="1.0" encoding="UTF-8"?>
+//    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+//    <plist version="1.0">
+//    <dict>
+//      <key>/</key>
+//      <dict>
+//        <key>hello/</key>
+//        <dict>
+//          <key>JVMUserOptions/</key>
+//          <dict>
+//            <key>-DXmx</key>
+//            <string>512m</string>
+//          </dict>
+//        </dict>
+//      </dict>
+//    </dict>
+//    </plist>
+//
+// 2. If the path is three or more, the first three become the domain name (even
+//    if shared across applicaitons) and the remaining become individual keys.
+//
+//    For example: If AppID = "com/hello/foo", the path is "hello/JVMUserOptions and the
+//    domain is "com.hello.foo" stored in the plist file ~/Library/Preferences/com.hello.foo.plist
+//    containing the contents:
+//
+//    <?xml version="1.0" encoding="UTF-8"?>
+//    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+//    <plist version="1.0">
+//    <dict>
+//      <key>/com/hello/foo/</key>
+//      <dict>
+//        <key>JVMUserOptions/</key>
+//        <dict>
+//          <key>-DXmx</key>
+//          <string>512m</string>
+//        </dict>
+//      </dict>
+//    </dict>
+//    </plist>
+//
+// NOTE: To change these values use the command line utility "defaults":
+// Example: defaults read com.apple.java.util.prefs /
+// Since OS 10.9 Mavericks the defaults are cashed so directly modifying the files is not recommended.
+bool MacJavaUserPreferences::Load(TString Appid) {
+    bool result = false;
+
+    if (Appid.empty() == false) {
+        // This is for backwards compatability. Older packaged applications have an
+        // app.preferences.id that is delimited by period (".") rather than
+        // slash ("/") so convert to newer style.
+        TString path = Helpers::ReplaceString(Appid, _T("."), _T("/"));
+
+        path = path + _T("/JVMUserOptions");
+        TString domainName;
+        std::list<TString> keys = Split(path, _T("/"));
+
+        // If there are less than three parts to the path then use the default preferences file.
+        if (keys.size() < 3) {
+            domainName = _T("com.apple.java.util.prefs");
+
+            // Append slash to the end of each key.
+            for (std::list<TString>::iterator iterator = keys.begin(); iterator != keys.end(); iterator++) {
+                TString item = *iterator;
+                item = item + _T("/");
+                *iterator = item;
+            }
+
+            // The root key is /.
+            keys.push_front(_T("/"));
+        }
+        else {
+            // Remove the first three keys and use them for the root key and the preferencesID.
+            TString one = keys.front();
+            keys.pop_front();
+            TString two = keys.front();
+            keys.pop_front();
+            TString three = keys.front();
+            keys.pop_front();
+            domainName = one + TString(".") + two + TString(".") + three;
+            domainName = toLowerCase(domainName);
+
+            // Append slash to the end of each key.
+            for (std::list<TString>::iterator iterator = keys.begin(); iterator != keys.end(); iterator++) {
+                TString item = *iterator;
+                item = item + _T("/");
+                *iterator = item;
+            }
+
+            // The root key is /one/two/three/
+            TString key = TString("/") + one + TString("/") + two + TString("/") + three + TString("/");
+            keys.push_front(key);
+        }
+
+        UserDefaults userDefaults(domainName);
+
+        if (userDefaults.Read(keys) == true) {
+            result = true;
+            FMap = userDefaults.GetData();
+        }
+    }
+
+    return result;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+#endif //MAC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/Main.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011, 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.packager;
+
+import jdk.packager.internal.Arguments;
+import jdk.packager.internal.Log;
+import jdk.packager.internal.CLIHelp;
+import java.io.PrintWriter;
+import java.util.ResourceBundle;
+
+public class Main {
+
+    private static final ResourceBundle bundle =
+            ResourceBundle.getBundle("jdk.packager.internal.resources.Bundle");
+
+    private static final String version = bundle.getString("MSG_Version")
+            + " " + System.getProperty("java.version") + "\n";
+
+    public static void main(String... args) throws Exception {
+        // Create logger with default system.out and system.err
+        Log.Logger logger = new Log.Logger(false);
+        Log.setLogger(logger);
+
+        int status = run(args);
+        System.exit(status);
+    }
+
+    public static int run(PrintWriter out, PrintWriter err, String... args)
+            throws Exception {
+        // Create logger with provided streams
+        Log.Logger logger = new Log.Logger(false);
+        logger.setPrintWriter(out, err);
+        Log.setLogger(logger);
+
+        int status = run(args);
+        Log.flush();
+        return status;
+    }
+
+    public static int run(String... args) throws Exception {
+        if (args.length == 0 || args.length == 1 && args[0].equals("--help")) {
+            CLIHelp.showHelp();
+        } else if (args.length == 1 && args[0].equals("--version")) {
+            Log.info(version);
+        } else {
+            try {
+                Arguments arguments = new Arguments(args);
+                arguments.processArguments();
+            } catch (Exception e) {
+                if (Arguments.verbose()) {
+                    throw e;
+                } else {
+                    Log.error(e.getMessage());
+                    if (e.getCause() != null && e.getCause() != e) {
+                        Log.error(e.getCause().getMessage());
+                    }
+                    return -1;
+                }
+            }
+        }
+
+        return 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/AbstractBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal;
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.Files;
+import java.text.MessageFormat;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+
+public abstract class AbstractBundler implements Bundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.AbstractBundler");
+
+    public static final BundlerParamInfo<File> IMAGES_ROOT =
+            new StandardBundlerParam<>(
+            I18N.getString("param.images-root.name"),
+            I18N.getString("param.images-root.description"),
+            "imagesRoot",
+            File.class,
+            params -> new File(
+                StandardBundlerParam.BUILD_ROOT.fetchFrom(params), "images"),
+            (s, p) -> null);
+
+    // do not use file separator -
+    // we use it for classpath lookup and there / are not platform specific
+    public final static String BUNDLER_PREFIX = "package/";
+
+    protected Class baseResourceLoader = null;
+
+    protected void fetchResource(
+            String publicName, String category,
+            String defaultName, File result, boolean verbose, File publicRoot)
+            throws IOException {
+        InputStream is = streamResource(publicName, category,
+                defaultName, verbose, publicRoot);
+        if (is != null) {
+            Files.copy(is, result.toPath(),
+                    StandardCopyOption.REPLACE_EXISTING);
+        } else {
+            if (verbose) {
+                Log.info(MessageFormat.format(I18N.getString(
+                        "message.using-default-resource"), 
+                        category == null ? "" : "[" + category + "] ",
+                        publicName));
+            }
+        }
+    }
+
+    protected void fetchResource(
+            String publicName, String category,
+            File defaultFile, File result, boolean verbose, File publicRoot)
+            throws IOException {
+        InputStream is = streamResource(publicName, category,
+                null, verbose, publicRoot);
+        if (is != null) {
+            Files.copy(is, result.toPath());
+        } else {
+            IOUtils.copyFile(defaultFile, result);
+            if (verbose) {
+                Log.info(MessageFormat.format(I18N.getString(
+                        "message.using-custom-resource-from-file"),
+                        category == null ? "" : "[" + category + "] ",
+                        defaultFile.getAbsoluteFile()));
+            }
+        }
+    }
+
+    private InputStream streamResource(String publicName, String category,
+            String defaultName, boolean verbose, File publicRoot)
+            throws IOException {
+        boolean custom = false;
+        InputStream is = null;
+        if (publicName != null) {
+            if (publicRoot != null) {
+                File publicResource = new File(publicRoot, publicName);
+                if (publicResource.exists() && publicResource.isFile()) {
+                    is = new FileInputStream(publicResource);
+                }
+            } else {
+                is = baseResourceLoader.getClassLoader().getResourceAsStream(
+                        publicName);
+            }
+            custom = (is != null);
+        }
+        if (is == null && defaultName != null) {
+            is = baseResourceLoader.getResourceAsStream(defaultName);
+        }
+        String msg = null;
+        if (custom) {
+            msg = MessageFormat.format(I18N.getString(
+                    "message.using-custom-resource-from-classpath"),
+                    category == null ? "" : "[" + category + "] ", publicName);
+        } else if (is != null) {
+            msg = MessageFormat.format(I18N.getString(
+                    "message.using-default-resource-from-classpath"),
+                    category == null ? "" : "[" + category + "] ", publicName);
+        }
+        if (verbose && is != null) {
+            Log.info(msg);
+        }
+        return is;
+    }
+
+    protected String preprocessTextResource(String publicName, String category,
+            String defaultName, Map<String, String> pairs,
+            boolean verbose, File publicRoot) throws IOException {
+        InputStream inp = streamResource(
+                publicName, category, defaultName, verbose, publicRoot);
+        if (inp == null) {
+            throw new RuntimeException(
+                    "Jar corrupt? No " + defaultName + " resource!");
+        }
+
+        // read fully into memory
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int length;
+        while ((length = inp.read(buffer)) != -1) {
+            baos.write(buffer, 0, length);
+        }
+
+        // substitute
+        String result = new String(baos.toByteArray());
+        for (Map.Entry<String, String> e : pairs.entrySet()) {
+            if (e.getValue() != null) {
+                result = result.replace(e.getKey(), e.getValue());
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return getName();
+    }
+
+    @Override
+    public void cleanup(Map<String, ? super Object> params) {
+        if (!StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            try {
+                IOUtils.deleteRecursive(
+                        StandardBundlerParam.BUILD_ROOT.fetchFrom(params));
+            } catch (IOException e) {
+                Log.debug(e.getMessage());
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/AbstractImageBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, 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.packager.internal;
+
+import java.text.MessageFormat;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static jdk.packager.internal.StandardBundlerParam.*;
+
+
+/**
+ * Common utility methods used by app image bundlers.
+ */
+public abstract class AbstractImageBundler extends AbstractBundler {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.AbstractImageBundler");
+
+    public void imageBundleValidation(Map<String, ? super Object> p)
+             throws ConfigException {
+        StandardBundlerParam.validateMainClassInfoFromAppResources(p);
+
+        Map<String, String> userJvmOptions = USER_JVM_OPTIONS.fetchFrom(p);
+        if (userJvmOptions != null) {
+            for (Map.Entry<String, String> entry : userJvmOptions.entrySet()) {
+                if (entry.getValue() == null || entry.getValue().isEmpty()) {
+                    throw new ConfigException(
+                            MessageFormat.format(I18N.getString(
+                            "error.empty-user-jvm-option-value"),
+                            entry.getKey()), I18N.getString(
+                            "error.empty-user-jvm-option-value.advice"));
+                }
+            }
+        }
+
+        boolean hasMainJar = MAIN_JAR.fetchFrom(p) != null;
+        boolean hasMainModule =
+                StandardBundlerParam.MODULE.fetchFrom(p) != null;
+        boolean hasMainClass = MAIN_CLASS.fetchFrom(p) != null;
+        boolean jreInstaller = Arguments.CREATE_JRE_INSTALLER.fetchFrom(p);
+
+        if (!hasMainJar && !hasMainModule && !hasMainClass && !jreInstaller) {
+            throw new ConfigException(
+                    I18N.getString("error.no-application-class"),
+                    I18N.getString("error.no-application-class.advice"));
+        }
+    }
+
+    public static void extractFlagsFromVersion(
+            Map<String, ? super Object> params, String versionOutput) {
+        Pattern bitArchPattern = Pattern.compile("(\\d*)[- ]?[bB]it");
+        Matcher matcher = bitArchPattern.matcher(versionOutput);
+        if (matcher.find()) {
+            params.put(".runtime.bit-arch", matcher.group(1));
+        } else {
+            // presume 32 bit on no match
+            params.put(".runtime.bit-arch", "32");
+        }
+
+        Pattern oldVersionMatcher = Pattern.compile(
+                "java version \"((\\d+.(\\d+).\\d+)(_(\\d+)))?(-(.*))?\"");
+        matcher = oldVersionMatcher.matcher(versionOutput);
+        if (matcher.find()) {
+            params.put(".runtime.version", matcher.group(1));
+            params.put(".runtime.version.release", matcher.group(2));
+            params.put(".runtime.version.major", matcher.group(3));
+            params.put(".runtime.version.update", matcher.group(5));
+            params.put(".runtime.version.minor", matcher.group(5));
+            params.put(".runtime.version.security", matcher.group(5));
+            params.put(".runtime.version.patch", "0");
+            params.put(".runtime.version.modifiers", matcher.group(7));
+        } else {
+            Pattern newVersionMatcher = Pattern.compile(
+                   "java version \"((\\d+).(\\d+).(\\d+).(\\d+))(-(.*))?(\\+[^\"]*)?\"");
+            matcher = newVersionMatcher.matcher(versionOutput);
+            if (matcher.find()) {
+                params.put(".runtime.version", matcher.group(1));
+                params.put(".runtime.version.release", matcher.group(1));
+                params.put(".runtime.version.major", matcher.group(2));
+                params.put(".runtime.version.update", matcher.group(3));
+                params.put(".runtime.version.minor", matcher.group(3));
+                params.put(".runtime.version.security", matcher.group(4));
+                params.put(".runtime.version.patch", matcher.group(5));
+                params.put(".runtime.version.modifiers", matcher.group(7));
+            } else {
+                params.put(".runtime.version", "");
+                params.put(".runtime.version.release", "");
+                params.put(".runtime.version.major", "");
+                params.put(".runtime.version.update", "");
+                params.put(".runtime.version.minor", "");
+                params.put(".runtime.version.security", "");
+                params.put(".runtime.version.patch", "");
+                params.put(".runtime.version.modifiers", "");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/ArgAction.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 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.packager.internal;
+
+@FunctionalInterface
+public interface ArgAction {
+    public void execute();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/Arguments.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,850 @@
+/*
+ * Copyright (c) 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.packager.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.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;
+import jdk.packager.internal.bundlers.Bundler;
+import jdk.packager.internal.bundlers.BundleParams;
+
+public class Arguments {
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.Arguments");
+
+    private static final String IMAGE_MODE = "image";
+    private static final String INSTALLER_MODE = "installer";
+    private static final String JRE_INSTALLER_MODE = "jre-installer";
+
+    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";
+
+    public static final BundlerParamInfo<Boolean> CREATE_IMAGE =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.create-image.name"),
+                    I18N.getString("param.create-image.description"),
+                    IMAGE_MODE,
+                    Boolean.class,
+                    p -> Boolean.FALSE,
+                    (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
+                            true : Boolean.valueOf(s));
+
+    public static final BundlerParamInfo<Boolean> CREATE_INSTALLER =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.create-installer.name"),
+                    I18N.getString("param.create-installer.description"),
+                    INSTALLER_MODE,
+                    Boolean.class,
+                    p -> Boolean.FALSE,
+                    (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
+                            true : Boolean.valueOf(s));
+    
+    public static final BundlerParamInfo<Boolean> CREATE_JRE_INSTALLER =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.create-jre-installer.name"),
+                    I18N.getString("param.create-jre-installer.description"),
+                    JRE_INSTALLER_MODE,
+                    Boolean.class,
+                    p -> Boolean.FALSE,
+                    (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ?
+                            true : Boolean.valueOf(s));
+
+    // regexp for parsing args (for example, for secondary launchers)
+    private static Pattern pattern = Pattern.compile(
+          "(?:(?:([\"'])(?:\\\\\\1|.)*?(?:\\1|$))|(?:\\\\[\"'\\s]|[^\\s]))++");
+
+    private DeployParams deployParams = null;
+    private Bundler.BundleType bundleType = null;
+
+    private int pos = 0;
+    private List<String> argList = null;
+
+    private List<CLIOptions> allOptions = null;
+
+    private ArrayList<String> files = null;
+
+    private String input = null;
+    private String output = null;
+
+    private boolean hasMainJar = false;
+    private boolean hasMainClass = false;
+    private boolean hasMainModule = false;
+    private boolean hasTargetFormat = false;
+
+    private String mainJarPath = null;
+    
+    private static boolean echo = false;
+    private static boolean verbose = false;
+    private static boolean jreInstaller = false;
+
+    private List<jdk.packager.internal.Bundler> platformBundlers = null;
+
+    private List<SecondaryLauncherArguments> secondaryLaunchers = null;
+
+    private static Map<String, CLIOptions> argIds = new HashMap<>();
+    private static Map<String, CLIOptions> argShortIds = new HashMap<>();
+
+    {
+        // init maps for parsing arguments
+        EnumSet<CLIOptions> options = EnumSet.allOf(CLIOptions.class);
+
+        options.forEach(option -> {
+            argIds.put(option.getIdWithPrefix(), option);
+            if (option.getShortIdWithPrefix() != null) {
+                argShortIds.put(option.getShortIdWithPrefix(), option);
+            }
+        });
+    }
+
+    public Arguments(String[] args) {
+        initArgumentList(args);
+    }
+
+    public enum CLIOptions {
+        CREATE_IMAGE(IMAGE_MODE, OptionCategories.MODE, () -> {
+            context().bundleType = Bundler.BundleType.IMAGE;
+            context().deployParams.setTargetFormat("image");
+            setOptionValue(IMAGE_MODE, true);
+        }),
+
+        CREATE_INSTALLER(INSTALLER_MODE, OptionCategories.MODE, () -> {
+            setOptionValue(INSTALLER_MODE, true);
+            context().bundleType = Bundler.BundleType.INSTALLER;
+            String format = "installer";
+            if (hasNextArg()) {
+                String arg = popArg();
+                if (!arg.startsWith("-")) {
+                    format = arg.toLowerCase();
+                    context().hasTargetFormat = true;
+                } else {
+                    prevArg();
+                }
+            }
+            context().deployParams.setTargetFormat(format);
+        }),
+        
+        CREATE_JRE_INSTALLER(JRE_INSTALLER_MODE, OptionCategories.MODE, () -> {
+            setOptionValue(JRE_INSTALLER_MODE, true);
+            context().bundleType = Bundler.BundleType.INSTALLER;
+            String format = "installer";
+            if (hasNextArg()) {
+                String arg = popArg();
+                if (!arg.startsWith("-")) {
+                    format = arg.toLowerCase();
+                    context().hasTargetFormat = true;
+                } else {
+                    prevArg();
+                }
+            }
+            jreInstaller = true;
+            context().deployParams.setTargetFormat(format);
+            context().deployParams.setJreInstaller(true);
+        }),
+
+        INPUT ("input", "i", OptionCategories.PROPERTY, () -> {
+            context().input = popArg();
+            setOptionValue("input", context().input);
+        }),
+
+        OUTPUT ("output", "o", OptionCategories.PROPERTY, () -> {
+            context().output = popArg();
+            context().deployParams.setOutdir(new File(context().output));
+        }),
+
+        DESCRIPTION ("description", "d", OptionCategories.PROPERTY),
+
+        VENDOR ("vendor", OptionCategories.PROPERTY),
+
+        APPCLASS ("class", "c", OptionCategories.PROPERTY, () -> {
+            context().hasMainClass = true;
+            setOptionValue("class", popArg());
+        }),
+
+        SINGLETON ("singleton", OptionCategories.PROPERTY, () -> {
+            setOptionValue("singleton", true);
+        }),
+
+        NAME ("name", "n", OptionCategories.PROPERTY),
+
+        IDENTIFIER ("identifier", OptionCategories.PROPERTY),
+
+        VERBOSE ("verbose", OptionCategories.PROPERTY, () -> {
+            setOptionValue("verbose", true);
+            verbose = true;
+        }),
+
+        FILES ("files", "f", OptionCategories.PROPERTY, () -> {
+              context().files = new ArrayList<>();
+              String files = popArg();
+              // TODO: should we split using ' '(space) ?
+              context().files.addAll(
+                      Arrays.asList(files.split(File.pathSeparator)));
+        }),
+
+        ARGUMENTS ("arguments", "a", OptionCategories.PROPERTY, () -> {
+            List<String> arguments = getArgumentList(popArg());
+            setOptionValue("arguments", arguments);
+        }),
+
+        STRIP_NATIVE_COMMANDS ("strip-native-commands",
+                   OptionCategories.PROPERTY, () -> {
+            setOptionValue("strip-native-commands", true);
+        }),
+
+        ICON ("icon", OptionCategories.PROPERTY),
+        CATEGORY ("category", OptionCategories.PROPERTY),
+        COPYRIGHT ("copyright", OptionCategories.PROPERTY),
+
+        LICENSE_FILE ("license-file", OptionCategories.PROPERTY),
+
+        VERSION ("version", "v", OptionCategories.PROPERTY),
+
+        JVM_ARGS ("jvm-args", OptionCategories.PROPERTY, () -> {
+            List<String> args = getArgumentList(popArg());
+            args.forEach(a -> setOptionValue("jvm-args", a));
+        }),
+
+        USER_JVM_ARGS ("user-jvm-args", OptionCategories.PROPERTY, () -> {
+            List<String> args = getArgumentList(popArg());
+            args.forEach(a -> setOptionValue("user-jvm-args", 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);
+
+        }),
+
+        SECONDARY_LAUNCHER ("secondary-launcher",
+                    OptionCategories.PROPERTY, () -> {
+            context().secondaryLaunchers.add(
+                new SecondaryLauncherArguments(popArg()));
+        }),
+
+        BUILD_ROOT ("build-root", OptionCategories.PROPERTY),
+        
+        INSTALL_DIR ("install-dir", OptionCategories.PROPERTY),
+
+        ECHO_MODE ("echo-mode", OptionCategories.PROPERTY, () -> {
+            echo = true;
+            setOptionValue("echo-mode", true);
+        }),
+
+        PREDEFINED_APP_IMAGE ("app-image", OptionCategories.PROPERTY),
+        
+        PREDEFINED_RUNTIME_IMAGE ("runtime-image", OptionCategories.PROPERTY),
+
+        MAIN_JAR ("main-jar", "j", 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),
+        
+        LIMIT_MODULES ("limit-modules", OptionCategories.MODULAR),
+
+        MAC_SIGN ("mac-sign", "s", OptionCategories.PLATFORM_MAC, () -> {
+            setOptionValue("mac-sign", true);
+        }),
+
+        MAC_BUNDLE_NAME ("mac-bundle-name", OptionCategories.PLATFORM_MAC),
+        
+        MAC_BUNDLE_IDENTIFIER("mac-bundle-identifier",
+                    OptionCategories.PLATFORM_MAC),
+
+        MAC_APP_STORE_CATEGORY ("mac-app-store-category",
+                    OptionCategories.PLATFORM_MAC),
+
+        MAC_BUNDLE_SIGNING_PREFIX ("mac-bundle-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_REGISTRY_NAME ("win-registry-name", OptionCategories.PLATFORM_WIN),
+
+        WIN_MSI_UPGRADE_UUID ("win-upgrade-uuid",
+                OptionCategories.PLATFORM_WIN),
+        
+        LINUX_BUNDLE_NAME ("linux-bundle-name",
+                OptionCategories.PLATFORM_LINUX),
+
+        LINUX_DEB_MAINTAINER ("linux-deb-maintainer",
+                OptionCategories.PLATFORM_LINUX),
+
+        LINUX_RPM_LICENSE_TYPE ("linux-rpm-license-type",
+                OptionCategories.PLATFORM_LINUX),
+
+        LINUX_PACKAGE_DEPENDENCIES ("linux-package-deps",
+                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;
+        }
+
+        public static void setContext(Arguments context) {
+            argContext = context;
+        }
+
+        private static Arguments context() {
+            if (argContext != null) {
+                return argContext;
+            } else {
+                throw new RuntimeException("Argument context is not set.");
+            }
+        }
+
+        public String getId() {
+            return this.id;
+        }
+
+        public String getIdWithPrefix() {
+            String prefix = isMode() ? "create-" : "--";
+            return prefix + this.id;
+        }
+
+        public String getShortIdWithPrefix() {
+            return this.shortId == null ? null : "-" + this.shortId;
+        }
+
+        public void execute() {
+            if (action != null) {
+                action.execute();
+            } else {
+                defaultAction();
+            }
+        }
+
+        public boolean isMode() {
+            return category == OptionCategories.MODE;
+        }
+
+        public OptionCategories getCategory() {
+            return category;
+        }
+
+        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 void prevArg() {
+            context().pos--;
+        }
+
+        private static boolean hasNextArg() {
+            return context().pos < context().argList.size();
+        }
+    }
+
+    public enum OptionCategories {
+        MODE,
+        MODULAR,
+        PROPERTY,
+        PLATFORM_MAC,
+        PLATFORM_WIN,
+        PLATFORM_LINUX;
+    }
+
+    private void initArgumentList(String[] args) {
+        argList = new ArrayList<>(Arrays.asList(args));
+        pos = 0;
+
+        deployParams = new DeployParams();
+        bundleType = Bundler.BundleType.NONE;
+
+        allOptions = new ArrayList<>();
+        
+        secondaryLaunchers = new ArrayList<>();
+    }
+
+    public boolean processArguments() throws Exception {
+        try {
+
+            // init context of arguments
+            CLIOptions.setContext(this);
+
+            // parse cmd line
+            String arg;
+            CLIOptions option;
+            for (; CLIOptions.hasNextArg(); CLIOptions.nextArg()) {
+                arg = CLIOptions.getArg();
+                // check if it's a CLI option
+                if ((option = toCLIOption(arg)) != null) {
+                    allOptions.add(option);
+                    option.execute();
+                } else {
+                    Log.info("Illegal argument ["+arg+"]");
+                }
+            }
+
+            if (allOptions.isEmpty() || !allOptions.get(0).isMode()) {
+                // first argument should always be a mode.
+                Log.info("ERROR: Mode is not specified");
+                return false;
+            }
+
+            if (!hasMainJar && !hasMainModule &&
+                    !hasMainClass && !jreInstaller) {
+                Log.info("ERROR: Main jar or main class or main module "
+                        + "must be specified.");
+            } else if (!hasMainModule && !hasMainClass) {
+                // try to get main-class from manifest
+                String mainClass = getMainClassFromManifest();
+                if (mainClass != null) {
+                    CLIOptions.setOptionValue(
+                            CLIOptions.APPCLASS.getId(), mainClass);
+                }
+            }
+
+            // display warning for arguments that are not supported
+            // for current configuration.
+
+            validateArguments();
+
+            addResources(deployParams, input, files);
+
+            deployParams.setBundleType(bundleType);
+
+            List<Map<String, ? super Object>> launchersAsMap =
+                    new ArrayList<>();
+
+            for (SecondaryLauncherArguments sl : secondaryLaunchers) {
+                launchersAsMap.add(sl.getLauncherMap());
+            }
+
+            deployParams.addBundleArgument(
+                    StandardBundlerParam.SECONDARY_LAUNCHERS.getID(),
+                    launchersAsMap);
+
+            // at this point deployParams should be already configured
+
+            deployParams.validate();
+
+            BundleParams bp = deployParams.getBundleParams();
+
+            generateBundle(bp.getBundleParamsAsMap());
+        } catch (Exception e) {
+            if (verbose) {
+                throw e;
+            } else {
+                System.err.println(e.getMessage());
+                if (e.getCause() != null && e.getCause() != e) {
+                    System.err.println(e.getCause().getMessage());
+                }
+                System.exit(-1);
+            }
+        }
+        return true;
+    }
+
+    private void validateArguments() {
+        CLIOptions mode = allOptions.get(0);
+        for (CLIOptions option : allOptions) {
+            if(!ValidOptions.checkIfSupported(mode, option)) {
+              System.out.println("WARNING: argument ["
+                      + option.getId() + "] is not "
+                      + "supported for current configuration.");  
+            }
+        }
+    }
+
+    private List<jdk.packager.internal.Bundler> getPlatformBundlers() {
+
+        if (platformBundlers != null) {
+            return platformBundlers;
+        }
+
+        platformBundlers = new ArrayList<>();
+        for (jdk.packager.internal.Bundler bundler :
+                Bundlers.createBundlersInstance().getBundlers(
+                        bundleType.toString())) {
+            if (hasTargetFormat && deployParams.getTargetFormat() != null && 
+                    !deployParams.getTargetFormat().equalsIgnoreCase(
+                    bundler.getID())) {
+                continue;
+            }
+            if (bundler.supported()) {
+                 platformBundlers.add(bundler);
+            }
+        }
+
+        return platformBundlers;
+    }
+
+    private void generateBundle(Map<String,? super Object> params)
+            throws PackagerException {
+        for (jdk.packager.internal.Bundler bundler : getPlatformBundlers()) {
+            Map<String, ? super Object> localParams = new HashMap<>(params);
+            try {
+                if (bundler.validate(localParams)) {
+                    File result =
+                            bundler.execute(localParams, deployParams.outdir);
+                    bundler.cleanup(localParams);
+                    if (result == null) {
+                        throw new PackagerException("MSG_BundlerFailed",
+                                bundler.getID(), bundler.getName());
+                    }
+                }
+            } catch (UnsupportedPlatformException e) {
+                Log.debug(MessageFormat.format(
+                        I18N.getString("MSG_BundlerPlatformException"),
+                        bundler.getName()));
+            } catch (ConfigException e) {
+                Log.debug(e);
+                if (e.getAdvice() != null) {
+                    Log.info(MessageFormat.format(
+                            I18N.getString("MSG_BundlerConfigException"),
+                            bundler.getName(), e.getMessage(), e.getAdvice()));
+                } else {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "MSG_BundlerConfigExceptionNoAdvice"),
+                            bundler.getName(), e.getMessage()));
+                }
+            } catch (RuntimeException re) {
+                Log.info(MessageFormat.format(
+                        I18N.getString("MSG_BundlerRuntimeException"),
+                        bundler.getName(), re.toString()));
+                Log.debug(re);
+            }
+        }
+    }
+
+    private void addResources(CommonParams commonParams,
+            String inputdir, List<String> inputfiles) {
+
+        if (inputdir == null || inputdir.isEmpty()) {
+            return;
+        }
+
+        File baseDir = new File(inputdir);
+
+        if (!baseDir.isDirectory()) {
+            Log.info(
+                    "Unable to add resources: \"-srcdir\" is not a directory.");
+            return;
+        }
+
+        List<String> fileNames;
+        if (inputfiles != null) {
+            fileNames = inputfiles;
+        } else {
+            // "-files" is omitted, all files in input cdir (which
+            // is a mandatory argument in this case) will be packaged.
+            fileNames = new ArrayList<>();
+            try (Stream<Path> files = Files.list(baseDir.toPath())) {
+                files.forEach(file -> fileNames.add(
+                        file.getFileName().toString()));
+            } catch (IOException e) {
+                Log.info("Unable to add resources: " + e.getMessage());
+            }
+        }
+        fileNames.forEach(file -> commonParams.addResource(baseDir, file));
+        setClasspath(fileNames);
+    }
+
+    private void setClasspath(List<String> inputfiles) {
+        String classpath = "";
+        for (String file : inputfiles) {
+            if (file.endsWith(".jar")) {
+                classpath += file;
+                classpath += File.pathSeparator;
+            }
+        }
+        deployParams.addBundleArgument(
+                StandardBundlerParam.CLASSPATH.getID(), classpath);
+    }
+
+    public static boolean isCLIOption(String arg) {
+        return toCLIOption(arg) != null;
+    }
+
+    public static CLIOptions toCLIOption(String arg) {
+        CLIOptions option;
+        if ((option = argIds.get(arg)) == null) {
+            option = argShortIds.get(arg);
+        }
+        return option;
+    }
+
+    static Map<String, String> getArgumentMap(String inputString) {
+        Map<String, String> map = new HashMap<>();
+        List<String> list = getArgumentList(inputString);
+        for (String pair : list) {
+            int equals = pair.indexOf("=");
+            if (equals != -1) {
+                String key = pair.substring(0, equals);
+                String value = pair.substring(equals+1, pair.length());
+                map.put(key, value);
+            }
+        }
+        return map;
+    }
+
+    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);
+            in.close();
+        } catch (IOException e) {
+            Log.info("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;
+    }
+
+    public static boolean echoMode() {
+        return echo;
+    }
+
+    public static boolean verbose() {
+        return verbose;
+    }
+
+    public static boolean isJreInstaller() {
+        return jreInstaller;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/BasicBundlers.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.ServiceLoader;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * A basic bundlers collection that loads the OpenJFX default bundlers.
+ * Loads the bundlers common to OpenJFX.
+ * <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));
+        }
+    }
+
+    @Override
+    public void loadDefaultBundlers() {
+        // no-op.  We now load all bundlers from module system.
+    }
+
+    // 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);
+        }
+    }
+    
+    @Override
+    public void loadBundler(Bundler bundler) {
+        bundlers.add(bundler);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/Bundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Map;
+
+public interface Bundler {
+    /**
+     * @return User Friendly name of this bundler.
+     */
+    String getName();
+
+    /**
+     * @return A more verbose description of the bundler.
+     */
+    String getDescription();
+
+    /**
+     * @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();
+
+    /**
+     * The parameters that this bundler uses to generate it's bundle.
+     * @return immutable collection
+     */
+    Collection<BundlerParamInfo<?>> getBundleParameters();
+
+    /**
+     * 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 UnsupportedPlatformException If the bundler cannot run on this
+     *         platform (i.e. creating mac apps on windows)
+     * @throws ConfigException If the configuration params are incorrect.  The
+     *         exception may contain advice on how to modify the params map
+     *         to make it valid.
+     */
+    boolean validate(Map<String, ? super Object> params)
+            throws UnsupportedPlatformException, 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 parameters as specified by getBundleParameters.
+     *               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);
+
+     /**
+     * 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();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/BundlerParamInfo.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal;
+
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+
+public class BundlerParamInfo<T> {
+    /**
+     * The user friendly name of the parameter
+     */
+    String name;
+
+    /**
+     * A more verbose description of the parameter
+     */
+    String description;
+
+    /**
+     * The command line and hashmap name of the parameter
+     */
+    String id;
+
+    /**
+     * Type of the parameter.  Typically String.class
+     */
+    Class<T> valueType;
+
+    /**
+     * 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;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getID() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public Class<T> getValueType() {
+        return valueType;
+    }
+
+    public void setValueType(Class<T> valueType) {
+        this.valueType = valueType;
+    }
+
+    public Function<Map<String, ? super Object>, T> getDefaultValueFunction() {
+        return defaultValueFunction;
+    }
+
+    public void setDefaultValueFunction(
+            Function<Map<String, ? super Object>, T> defaultValueFunction) {
+        this.defaultValueFunction = defaultValueFunction;
+    }
+
+    public BiFunction<String, Map<String, ? super Object>,T>
+            getStringConverter() {
+        return stringConverter;
+    }
+
+    public void setStringConverter(BiFunction<String,
+            Map<String, ? super Object>, T> stringConverter) {
+        this.stringConverter = stringConverter;
+    }
+
+    @SuppressWarnings("unchecked")
+    public final T fetchFrom(Map<String, ? super Object> params) {
+        return fetchFrom(params, true);
+    }
+
+    @SuppressWarnings("unchecked")
+    public 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 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);
+            }
+            return result;
+        }
+
+        // ultimate fallback
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/Bundlers.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+
+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 the bundlers common to the JDK.  A typical implementation
+     * would load:
+     * <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>
+     *
+     * This method is called from the
+     * {@link #createBundlersInstance(ClassLoader)}
+     * and {@link #createBundlersInstance()} methods.
+     * NOTE: Because of the module system this method is now not used.
+     */
+    void loadDefaultBundlers();
+
+    /**
+     * 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);
+
+    /**
+     * Loads a specific bundler into the set of bundlers.
+     * Useful for a manually configured bundler.
+     *
+     * @param bundler the specific bundler to add
+     */
+    void loadBundler(Bundler bundler);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/CLIHelp.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 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.packager.internal;
+
+import java.util.ResourceBundle;
+
+
+public class CLIHelp {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.CLIHelp");
+
+    // generates --help for jpackager's CLI
+    public static void showHelp() {
+        
+        Platform platform = Platform.getPlatform();
+        Log.info(I18N.getString("MSG_Help_common"));
+
+        switch (platform) {
+            case MAC:
+                Log.info(I18N.getString("MSG_Help_mac"));
+                break;
+            case LINUX:
+                Log.info(I18N.getString("MSG_Help_linux"));
+                break;
+            case WINDOWS:
+                Log.info(I18N.getString("MSG_Help_win"));
+                break;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/CommonParams.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011, 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.packager.internal;
+
+import java.io.File;
+
+
+public abstract class CommonParams {
+    File outdir;
+    boolean verbose;
+
+    public void setOutdir(File outdir) {
+        this.outdir = outdir;
+    }
+
+    public void setVerbose(boolean v) {
+        verbose = v;
+    }
+
+    public abstract void addResource(File baseDir, String path);
+
+    public abstract void addResource(File baseDir, File file);
+
+    public abstract void validate() throws PackagerException;
+
+    @Override
+    public String toString() {
+        return "CommonParams{" + "outdir=" + outdir
+                + " verbose=" + verbose + '}';
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/ConfigException.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal;
+
+
+public class ConfigException extends Exception {
+    final String advice;
+
+    public ConfigException(String msg, String advice) {
+        super(msg);
+        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.packager/share/classes/jdk/packager/internal/DeployParams.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,797 @@
+/*
+ * Copyright (c) 2011, 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.packager.internal;
+
+import jdk.packager.internal.bundlers.*;
+import jdk.packager.internal.bundlers.Bundler.BundleType;
+import java.io.File;
+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;
+
+public class DeployParams extends CommonParams {
+    public enum RunMode {
+        EMBEDDED, STANDALONE, ALL
+    }
+
+    final List<RelativeFileSet> resources = new ArrayList<>();
+
+    String id;
+    String title;
+    String vendor;
+    String email;
+    String description;
+    String category;
+    String licenseType;
+    String copyright;
+    String version;
+    Boolean systemWide;
+    Boolean serviceHint;
+    Boolean signBundle;
+    Boolean installdirChooser;
+    Boolean singleton;
+
+    String applicationClass;
+    String preloader;
+
+    List<Param> params;
+    List<String> arguments; //unnamed arguments
+
+    // Java 9 modules support
+    String addModules = null;
+    String limitModules = null;
+    Boolean stripNativeCommands = null;
+    Boolean detectmods = null;
+    String modulePath = null;
+    String module = null;
+    String debugPort = null;
+    String srcdir;
+
+    int width;
+    int height;
+    String embeddedWidth = null;
+    String embeddedHeight = null;
+
+    String appName;
+    String codebase;
+
+    @Deprecated final boolean embedCertificates = false;
+    boolean allPermissions = false;
+    String updateMode = "background";
+    boolean isExtension = false;
+    boolean isSwingApp = false;
+    
+    boolean jreInstaller = false;
+
+    Boolean needShortcut = null;
+    Boolean needMenu = null;
+    Boolean needInstall = null;
+
+    String outfile;
+    // if true then we cobundle js and image files needed
+    // for web deployment with the application
+    boolean includeDT;
+
+    String placeholder = "'javafx-app-placeholder'";
+    String appId = null;
+
+    // didn't have a setter...
+    boolean offlineAllowed = true;
+
+    String jrePlatform = System.getProperty("java.version")+"+";
+    File javaRuntimeToUse = null;
+    boolean javaRuntimeWasSet = false;
+
+    // list of jvm args
+    // (in theory string can contain spaces and need to be escaped
+    List<String> jvmargs = new LinkedList<>();
+    Map<String, String> jvmUserArgs = new LinkedHashMap<>();
+
+    // list of jvm properties (can also be passed as VM args
+    // but keeping them separate make it a bit more convinient
+    Map<String, String> properties = new LinkedHashMap<>();
+
+    // raw arguments to the bundler
+    Map<String, ? super Object> bundlerArguments = new LinkedHashMap<>();
+
+    String fallbackApp = null;
+
+    public void setJavaRuntimeSource(File src) {
+        javaRuntimeToUse = src;
+        javaRuntimeWasSet = true;
+    }
+
+    public void setCodebase(String codebase) {
+        this.codebase = codebase;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setCategory(String category) {
+        this.category = category;
+    }
+
+    public void setLicenseType(String licenseType) {
+        this.licenseType = licenseType;
+    }
+
+    public void setCopyright(String copyright) {
+        this.copyright = copyright;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public void setSystemWide(Boolean systemWide) {
+        this.systemWide = systemWide;
+    }
+
+    public void setServiceHint(Boolean serviceHint) {
+        this.serviceHint = serviceHint;
+    }
+
+    public void setInstalldirChooser(Boolean installdirChooser) {
+        this.installdirChooser = installdirChooser;
+    }
+
+    public void setSingleton(Boolean singleton) {
+        this.singleton = singleton;
+    }
+
+    public void setSignBundle(Boolean signBundle) {
+        this.signBundle = signBundle;
+    }
+
+    public void setJRE(String v) {
+        jrePlatform = v;
+    }
+
+    public void setSwingAppWithEmbeddedJavaFX(boolean v) {
+        isSwingApp = v;
+    }
+
+    public void setNeedInstall(boolean b) {
+        needInstall = b;
+    }
+
+    public void setOfflineAllowed(boolean b) {
+        offlineAllowed = b;
+    }
+
+    public void setNeedShortcut(Boolean b) {
+        needShortcut = b;
+    }
+
+    public void setEmbeddedDimensions(String w, String h) {
+        embeddedWidth = w;
+        embeddedHeight = h;
+    }
+
+    public void setFallback(String v) {
+        if (v == null) {
+            return;
+        }
+
+        if ("none".equals(v) || "null".equals(v)) {
+            fallbackApp = null;
+        } else {
+            fallbackApp = v;
+        }
+    }
+
+    public void addJvmArg(String v) {
+        jvmargs.add(v);
+    }
+
+    public void addJvmUserArg(String n, String v) {
+        jvmUserArgs.put(n, v);
+    }
+
+    public void addJvmProperty(String n, String v) {
+        properties.put(n, v);
+    }
+
+    public void setAllPermissions(boolean allPermissions) {
+        this.allPermissions = allPermissions;
+    }
+
+    public void setAppName(String appName) {
+        this.appName = appName;
+    }
+
+    public void setArguments(List<String> args) {
+        this.arguments = args;
+    }
+
+    public List<String> getArguments() {
+        return this.arguments;
+    }
+
+    public void addArgument(String arg) {
+        this.arguments.add(arg);
+    }
+
+    public void addAddModule(String value) {
+        if (addModules == null) {
+            addModules = value;
+        }
+        else {
+            addModules += "," + value;
+        }
+    }
+
+    public void addLimitModule(String value) {
+        if (limitModules == null) {
+            limitModules = value;
+        }
+        else {
+            limitModules += "," + value;
+        }
+    }
+
+    public String getModulePath() {
+        return this.modulePath;
+    }
+
+    public void setSrcdir(String srcdir) {
+        this.srcdir = srcdir;
+    }
+
+    public void setModulePath(String value) {
+        this.modulePath = value;
+    }
+
+    public void setModule(String value) {
+        this.module = value;
+    }
+
+    public void setDebug(String value) {
+        this.debugPort = value;
+    }
+
+    public void setStripNativeCommands(boolean value) {
+        this.stripNativeCommands = value;
+    }
+
+    public void setDetectModules(boolean value) {
+        this.detectmods = value;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public void setPlaceholder(String p) {
+        placeholder = p;
+    }
+
+    public void setAppId(String id) {
+        appId = id;
+    }
+
+    public void setHeight(int height) {
+        this.height = height;
+    }
+
+    public void setOutfile(String outfile) {
+        this.outfile = outfile;
+    }
+
+    public void setParams(List<Param> params) {
+        this.params = params;
+    }
+
+    public void setPreloader(String preloader) {
+        this.preloader = preloader;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public void setUpdateMode(String updateMode) {
+        this.updateMode = updateMode;
+    }
+
+    public void setVendor(String vendor) {
+        this.vendor = vendor;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public void setWidth(int width) {
+        this.width = width;
+    }
+
+    public void setExtension(boolean isExtension) {
+        this.isExtension = isExtension;
+    }
+
+    public void setApplicationClass(String applicationClass) {
+        this.applicationClass = applicationClass;
+    }
+
+    public void setIncludeDT(boolean doEmbed) {
+        includeDT = doEmbed;
+    }
+
+    public void setJreInstaller(boolean value) {
+        jreInstaller = value;
+    }
+
+    public File getOutdir() {
+        return this.outdir;
+    }
+
+    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 javapackager)
+    // 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 (jdk.packager.internal.IOUtils.isNotSymbolicLink(root)) {
+            if (root.isDirectory()) {
+                File[] children = root.listFiles();
+                if (children != null) {
+                    for (File f : children) {
+                        files.addAll(expandFileset(f));
+                    }
+                }
+            } else {
+                files.add(root);
+            }
+        }
+        return files;
+    }
+
+    @Override
+    public void addResource(File baseDir, String path) {
+        File file = new File(baseDir, path);
+        // normalize top level dir
+        // 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))));
+    }
+
+    @Override
+    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))));
+    }
+
+    public void addResource(File baseDir, String path, String type) {
+        addResource(baseDir, createFile(baseDir, path), type);
+    }
+
+    public void addResource(File baseDir, File file, String type) {
+        addResource(baseDir, file, "eager", type, null, null);
+    }
+
+    public void addResource(File baseDir, File file, String mode,
+            String type, String os, String arch) {
+        Set<File> singleFile = new LinkedHashSet<>();
+        singleFile.add(file);
+        if (baseDir == null) {
+            baseDir = file.getParentFile();
+        }
+        RelativeFileSet rfs = new RelativeFileSet(baseDir, singleFile);
+        rfs.setArch(arch);
+        rfs.setMode(mode);
+        rfs.setOs(os);
+        rfs.setType(parseTypeFromString(type, file));
+        resources.add(rfs);
+    }
+
+    private RelativeFileSet.Type parseTypeFromString(String type, File file) {
+        if (type == null) {
+            if (file.getName().endsWith(".jar")) {
+                return RelativeFileSet.Type.jar;
+            } else if (file.getName().endsWith(".jnlp")) {
+                return RelativeFileSet.Type.jnlp;
+            } else {
+                return RelativeFileSet.Type.UNKNOWN;
+            }
+        } else {
+            return RelativeFileSet.Type.valueOf(type);
+        }
+    }
+
+    private static File createFile(final File baseDir, final String path) {
+        final File testFile = new File(path);
+        return testFile.isAbsolute() ?
+                testFile : new File(baseDir == null ?
+                        null : baseDir.getAbsolutePath(), path);
+    }
+
+
+    @Override
+    public void validate() throws PackagerException {
+        if (outdir == null) {
+            throw new PackagerException("ERR_MissingArgument", "--output");
+        }
+
+        if (bundlerArguments.get(
+                Arguments.CLIOptions.MODULE.getId()) == null && !jreInstaller) {
+            if (resources.isEmpty()) {
+                throw new PackagerException("ERR_MissingAppResources");
+            }
+
+            if (bundlerArguments.get(
+                    Arguments.CLIOptions.APPCLASS.getId()) == null) {
+                throw new PackagerException("ERR_MissingArgument", "--class");
+            }
+        }
+    }
+
+    public boolean validateForBundle() {
+        boolean result = false;
+
+        // Success
+        if (((applicationClass != null && !applicationClass.isEmpty()) ||
+            (module != null && !module.isEmpty()))) {
+            result = true;
+        }
+
+        return result;
+    }
+
+    // could be icon or splash
+    // TODO: do we still need this class?
+    static class Icon {
+        final static int UNDEFINED = -1;
+
+        String href;
+        String kind;
+        int width = UNDEFINED;
+        int height = UNDEFINED;
+        int depth = UNDEFINED;
+        RunMode mode = RunMode.ALL;
+
+        Icon(String href, String kind, int w, int h, int d, RunMode m) {
+            mode = m;
+            this.href = href;
+            this.kind = kind;
+            if (w > 0) {
+                width = w;
+            }
+            if (h > 0) {
+                height = h;
+            }
+            if (d > 0) {
+                depth = d;
+            }
+        }
+    }
+
+    List<Icon> icons = new LinkedList<>();
+
+    public void addIcon(
+            String href, String kind, int w, int h, int d, RunMode m) {
+        icons.add(new Icon(href, kind, w, h, d, m));
+    }
+
+    BundleType bundleType = BundleType.NONE;
+    String targetFormat = null; //means any
+
+    public void setBundleType(BundleType type) {
+        bundleType = type;
+    }
+
+    public BundleType getBundleType() {
+        return bundleType;
+    }
+
+    public void setTargetFormat(String t) {
+        targetFormat = t;
+    }
+
+    public String getTargetFormat() {
+        return targetFormat;
+    }
+
+    private String getArch() {
+        String arch = System.getProperty("os.arch").toLowerCase();
+
+        if ("x86".equals(arch) || "i386".equals(arch) || "i486".equals(arch)
+                || "i586".equals(arch) || "i686".equals(arch)) {
+            arch = "x86";
+        } else if ("x86_64".equals(arch) || "amd64".equals("arch")) {
+            arch = "x86_64";
+        }
+
+        return arch;
+    }
+
+    static final Set<String> multi_args = new TreeSet<>(Arrays.asList(
+            StandardBundlerParam.JVM_PROPERTIES.getID(),
+            StandardBundlerParam.JVM_OPTIONS.getID(),
+            StandardBundlerParam.USER_JVM_OPTIONS.getID(),
+            StandardBundlerParam.ARGUMENTS.getID(),
+            StandardBundlerParam.MODULE_PATH.getID(),
+            StandardBundlerParam.ADD_MODULES.getID(),
+            StandardBundlerParam.LIMIT_MODULES.getID(),
+            StandardBundlerParam.STRIP_NATIVE_COMMANDS.getID(),
+            StandardBundlerParam.FILE_ASSOCIATIONS.getID(),
+            JLinkBundlerHelper.DETECT_MODULES.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) {
+                bundlerArguments.put(key, existingValue + "\n\n" + 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);
+        }
+    }
+
+    public BundleParams getBundleParams() {
+        BundleParams bundleParams = new BundleParams();
+
+        //construct app resources
+        //  relative to output folder!
+        String currentOS = System.getProperty("os.name").toLowerCase();
+        String currentArch = getArch();
+
+        for (RelativeFileSet rfs : resources) {
+            String os = rfs.getOs();
+            String arch = rfs.getArch();
+            //skip resources for other OS
+            // and nativelib jars (we are including raw libraries)
+            if ((os == null || currentOS.contains(os.toLowerCase())) &&
+                    (arch == null ||
+                    currentArch.startsWith(arch.toLowerCase())) &&
+                    rfs.getType() != RelativeFileSet.Type.nativelib) {
+                if (rfs.getType() == RelativeFileSet.Type.license) {
+                    for (String s : rfs.getIncludedFiles()) {
+                        bundleParams.addLicenseFile(s);
+                    }
+                }
+            }
+        }
+
+        bundleParams.setAppResourcesList(resources);
+
+        bundleParams.setIdentifier(id);
+
+        if (javaRuntimeWasSet) {
+            bundleParams.setRuntime(javaRuntimeToUse);
+        }
+        bundleParams.setApplicationClass(applicationClass);
+        bundleParams.setPrelaoderClass(preloader);
+        bundleParams.setName(this.appName);
+        bundleParams.setAppVersion(version);
+        bundleParams.setType(bundleType);
+        bundleParams.setBundleFormat(targetFormat);
+        bundleParams.setVendor(vendor);
+        bundleParams.setEmail(email);
+        bundleParams.setServiceHint(serviceHint);
+        bundleParams.setInstalldirChooser(installdirChooser);
+        bundleParams.setSingleton(singleton);
+        bundleParams.setCopyright(copyright);
+        bundleParams.setApplicationCategory(category);
+        bundleParams.setDescription(description);
+        bundleParams.setTitle(title);
+        if (verbose) bundleParams.setVerbose(true);
+
+        bundleParams.setJvmProperties(properties);
+        bundleParams.setJvmargs(jvmargs);
+        bundleParams.setJvmUserArgs(jvmUserArgs);
+        bundleParams.setArguments(arguments);
+
+        if (addModules != null && !addModules.isEmpty()) {
+            bundleParams.setAddModules(addModules);
+        }
+
+        if (limitModules != null && !limitModules.isEmpty()) {
+            bundleParams.setLimitModules(limitModules);
+        }
+
+        if (stripNativeCommands != null) {
+            bundleParams.setStripNativeCommands(stripNativeCommands);
+        }
+
+        bundleParams.setSrcDir(srcdir);
+
+        if (modulePath != null && !modulePath.isEmpty()) {
+            bundleParams.setModulePath(modulePath);
+        }
+
+        if (module != null && !module.isEmpty()) {
+            bundleParams.setMainModule(module);
+        }
+
+        if (debugPort != null && !debugPort.isEmpty()) {
+            bundleParams.setDebug(debugPort);
+        }
+
+        if (detectmods != null) {
+            bundleParams.setDetectMods(detectmods);
+        }
+
+        File appIcon = null;
+        List<Map<String, ? super Object>> bundlerIcons = new ArrayList<>();
+        for (Icon ic: icons) {
+            // NB: in theory we should be paying attention to RunMode but
+            // currently everything is marked as webstart internally and
+            // runmode is not publicly documented property
+            if (/* (ic.mode == RunMode.ALL ||
+                    ic.mode == RunMode.STANDALONE) && */
+                (ic.kind == null || ic.kind.equals("default")))
+            {
+                //could be full path or something relative to the output folder
+                appIcon = new File(ic.href);
+                if (!appIcon.exists()) {
+                    jdk.packager.internal.Log.debug(
+                        "Icon [" + ic.href + "] is not valid absolute path. "
+                        + "Assume it is relative to the output dir.");
+                    appIcon = new File(outdir, ic.href);
+                }
+            }
+
+            Map<String, ? super Object> iconInfo = new TreeMap<>();
+/*
+            if (ic.href != null) iconInfo.put(ICONS_HREF.getID(), ic.href);
+            if (ic.kind != null) iconInfo.put(ICONS_KIND.getID(), ic.kind);
+            if (ic.width > 0)    iconInfo.put(ICONS_WIDTH.getID(),
+                    Integer.toString(ic.width));
+            if (ic.height > 0)   iconInfo.put(ICONS_HEIGHT.getID(),
+                    Integer.toString(ic.height));
+            if (ic.depth > 0)    iconInfo.put(ICONS_DEPTH.getID(),
+                    Integer.toString(ic.depth));
+*/
+            if (!iconInfo.isEmpty()) bundlerIcons.add(iconInfo);
+        }
+        // putUnlessNullOrEmpty(ICONS.getID(), bundlerIcons);
+
+        bundleParams.setIcon(appIcon);
+
+        Map<String, String> paramsMap = new TreeMap<>();
+        if (params != null) {
+            for (Param p : params) {
+                paramsMap.put(p.name, p.value);
+            }
+        }
+
+        Map<String, String> unescapedHtmlParams = new TreeMap<>();
+        Map<String, String> escapedHtmlParams = new TreeMap<>();
+        
+        // putUnlessNullOrEmpty(JNLPBundler.APPLET_PARAMS.getID(),
+        //         unescapedHtmlParams);
+        // putUnlessNullOrEmpty(ESCAPED_APPLET_PARAMS.getID(),
+        //          escapedHtmlParams);
+
+/*
+        putUnlessNull(WIDTH.getID(), width);
+        putUnlessNull(HEIGHT.getID(), height);
+        putUnlessNull(EMBEDDED_WIDTH.getID(), embeddedWidth);
+        putUnlessNull(EMBEDDED_HEIGHT.getID(), embeddedHeight);
+
+        putUnlessNull(CODEBASE.getID(), codebase);
+        putUnlessNull(EMBED_JNLP.getID(), embedJNLP);
+        // embedCertificates
+        putUnlessNull(ALL_PERMISSIONS.getID(), allPermissions);
+        putUnlessNull(UPDATE_MODE.getID(), updateMode);
+        putUnlessNull(EXTENSION.getID(), isExtension);
+        putUnlessNull(SWING_APP.getID(), isSwingApp);
+
+        putUnlessNull(OUT_FILE.getID(), outfile);
+        putUnlessNull(INCLUDE_DT.getID(), includeDT);
+        putUnlessNull(PLACEHOLDER.getID(), placeholder);
+        putUnlessNull(OFFLINE_ALLOWED.getID(), offlineAllowed);
+
+        putUnlessNull(TEMPLATES.getID(), templatesMap);
+
+        putUnlessNull(FX_PLATFORM.getID(), fxPlatform);
+        putUnlessNull(JRE_PLATFORM.getID(), jrePlatform);
+
+        putUnlessNull(FALLBACK_APP.getID(), fallbackApp);
+*/
+        // 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;
+    }
+
+    public Map<String, ? super Object> getBundlerArguments() {
+        return this.bundlerArguments;
+    }
+
+    public void putUnlessNull(String param, Object value) {
+        if (value != null) {
+            bundlerArguments.put(param, value);
+        }
+    }
+
+    public void putUnlessNullOrEmpty(String param, Map<?, ?> value) {
+        if (value != null && !value.isEmpty()) {
+            bundlerArguments.put(param, value);
+        }
+    }
+
+    public void putUnlessNullOrEmpty(String param, Collection<?> value) {
+        if (value != null && !value.isEmpty()) {
+            bundlerArguments.put(param, value);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/EnumeratedBundlerParam.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal;
+
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ *
+ * The class 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>
+ *
+ */
+public class EnumeratedBundlerParam<T> extends BundlerParamInfo<T> {
+    // Not sure if this is the correct order, my idea is that from and IDE's
+    // 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;
+
+    public EnumeratedBundlerParam(String name, String description,
+            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.name = name;
+        this.description = description;
+        this.id = id;
+        this.valueType = valueType;
+        this.defaultValueFunction = defaultValueFunction;
+        this.stringConverter = stringConverter;
+        this.elements = elements;
+        this.strict = strict;
+    }
+
+    public boolean isInPossibleValues(T value) {
+        return elements.values().contains(value);
+    }
+
+    // Having the displayable values as the keys seems a bit wacky
+    public Set<String> getDisplayableKeys() {
+        return Collections.unmodifiableSet(elements.keySet());
+    }
+
+    // mapping from a "displayable" key to an "identifier" value.
+    public T getValueForDisplayableKey(String displayableKey) {
+        return elements.get(displayableKey);
+    }
+
+    public boolean isStrict() {
+        return strict;
+    }
+
+    public boolean isLoose() {
+        return !isStrict();
+    }
+
+    public T validatedFetchFrom(Map<String, ? super Object> params)
+            throws InvalidBundlerParamException {
+        if (isStrict()) {
+            T value = fetchFrom(params);
+            if (!isInPossibleValues(value)) {
+                throw new InvalidBundlerParamException("Parameter "
+                        + value.toString()
+                        + " not in valid set of values for BundlerParam "
+                        + name);
+            }
+            return value;
+        }
+        return fetchFrom(params);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/IOUtils.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal;
+
+import java.io.*;
+import java.net.URL;
+import java.util.Arrays;
+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.ArrayList;
+import java.util.List;
+
+
+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 {
+        Files.walkFileTree(src, new SimpleFileVisitor<Path>() {
+            @Override
+            public FileVisitResult preVisitDirectory(final Path dir,
+                    final BasicFileAttributes attrs) throws IOException {
+                Files.createDirectories(dest.resolve(src.relativize(dir)));
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult visitFile(final Path file,
+                    final BasicFileAttributes attrs) throws IOException {
+                Files.copy(file, dest.resolve(src.relativize(file)));
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    public static void copyFromURL(URL location, File file) throws IOException {
+        copyFromURL(location, file, false);
+    }
+
+    public static void copyFromURL(URL location, File file, boolean append)
+            throws IOException {
+        if (location == null) {
+            throw new IOException("Missing input resource!");
+        }
+        if (file.exists() && !append) {
+           file.delete();
+        }
+        InputStream in = location.openStream();
+        FileOutputStream out = new FileOutputStream(file, append);
+        byte[] buffer = new byte[1024];
+        int len;
+        while ((len = in.read(buffer)) != -1) {
+            out.write(buffer, 0, len);
+        }
+        out.close();
+        in.close();
+        file.setReadOnly();
+        file.setReadable(true, false);
+    }
+
+    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();
+
+        FileChannel source = null;
+        FileChannel destination = null;
+        source = new FileInputStream(sourceFile).getChannel();
+        destination = new FileOutputStream(destFile).getChannel();
+        if (destination != null && source != null) {
+            destination.transferFrom(source, 0, source.size());
+        }
+        if (source != null) {
+            source.close();
+        }
+        if (destination != null) {
+            destination.close();
+        }
+
+        //preserve executable bit!
+        if (sourceFile.canExecute()) {
+            destFile.setExecutable(true, false);
+        }
+        if (!sourceFile.canWrite()) {
+            destFile.setReadOnly();
+        }
+        destFile.setReadable(true, false);
+    }
+
+    public static long getFolderSize(File folder) {
+        long foldersize = 0;
+
+        File[] children = folder.listFiles();
+        if (children != null) {
+            for (File f : children) {
+                if (f.isDirectory()) {
+                    foldersize += getFolderSize(f);
+                } else {
+                    foldersize += f.length();
+                }
+            }
+        }
+
+        return foldersize;
+    }
+
+    //run "launcher paramfile" in the directory where paramfile is kept
+    public static void run(String launcher, File paramFile, boolean verbose)
+            throws IOException {
+        if (paramFile != null && paramFile.exists()) {
+            ProcessBuilder pb =
+                    new ProcessBuilder(launcher, paramFile.getName());
+            pb = pb.directory(paramFile.getParentFile());
+            exec(pb, verbose);
+        }
+    }
+
+    public static void exec(ProcessBuilder pb, boolean verbose)
+            throws IOException {
+        exec(pb, verbose, false);
+    }
+
+    public static void exec(ProcessBuilder pb, boolean verbose,
+            boolean testForPresenseOnly) throws IOException {
+        exec(pb, verbose, testForPresenseOnly, null);
+    }
+
+    public static void exec(ProcessBuilder pb, boolean verbose,
+            boolean testForPresenseOnly, PrintStream consumer)
+            throws IOException {
+        pb.redirectErrorStream(true);
+        String prefix = Arguments.echoMode() ? "\nECHO-MODE: " : "";
+        Log.verbose(prefix + "Running "
+                + Arrays.toString(pb.command().toArray(new String[0]))
+                + (pb.directory() != null ? (" in " + pb.directory()) : ""));
+        Process p = pb.start();
+        InputStreamReader isr = new InputStreamReader(p.getInputStream());
+        BufferedReader br = new BufferedReader(isr);
+        String lineRead;
+        while ((lineRead = br.readLine()) != null) {
+            if (consumer != null) {
+                consumer.print(lineRead + '\n');
+            } else if (verbose) {
+               Log.info(lineRead);
+            } else {
+               Log.debug(lineRead);
+            }
+        }
+        try {
+            int ret = p.waitFor();
+            if (ret != 0 && !(testForPresenseOnly && ret != 127)) {
+                throw new IOException("Exec failed with code "
+                        + ret + " command ["
+                        + Arrays.toString(pb.command().toArray(new String[0]))
+                        + " in " + (pb.directory() != null ?
+                                pb.directory().getAbsolutePath() :
+                                "unspecified directory"));
+            }
+        } catch (InterruptedException ex) {
+        }
+
+        if (Arguments.echoMode()) {
+             Log.verbose("\n");
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static Process startProcess(Object... args) throws IOException {
+        final ArrayList<String> argsList = new ArrayList<>();
+        for (Object a : args) {
+            if (a instanceof List) {
+                argsList.addAll((List)a);
+            } else if (a instanceof String) {
+                argsList.add((String)a);
+            }
+        }
+
+        return Runtime.getRuntime().exec(
+                argsList.toArray(new String[argsList.size()]));
+    }
+
+    private static void logErrorStream(Process p) {
+        final BufferedReader err =
+                new BufferedReader(new InputStreamReader(p.getErrorStream()));
+        Thread t = new Thread(() -> {
+            try {
+                String line;
+                while ((line = err.readLine()) != null) {
+                    Log.error(line);
+                }
+            } catch (IOException ioe) {
+                Log.verbose(ioe);
+            }
+        });
+        t.setDaemon(true);
+        t.start();
+    }
+
+    public static int getProcessOutput(List<String> result, Object... args)
+            throws IOException, InterruptedException {
+        final Process p = startProcess(args);
+
+        List<String> list = new ArrayList<>();
+        final BufferedReader in =
+                new BufferedReader(new InputStreamReader(p.getInputStream()));
+        Thread t = new Thread(() -> {
+            try {
+                String line;
+                while ((line = in.readLine()) != null) {
+                    list.add(line);
+                }
+            } catch (IOException ioe) {
+                jdk.packager.internal.Log.verbose(ioe);
+            }
+        });
+        t.setDaemon(true);
+        t.start();
+
+        logErrorStream(p);
+
+        int ret = p.waitFor();
+
+        result.clear();
+        result.addAll(list);
+
+        return ret;
+    }
+
+    // no good test if we are running pre-JRE7
+    // use heuristic approach
+    // "false positive" is better than wrong answer
+    public static boolean isNotSymbolicLink(File file) {
+        //no symlinks on windows
+        if (Platform.getPlatform() == Platform.WINDOWS) {
+            return true;
+        }
+        try {
+            if (file == null || file.getParent() == null) {
+                return false;
+            }
+            File file_canonical = new File(
+                    file.getParentFile().getCanonicalFile(), file.getName());
+            if (file_canonical.getCanonicalFile().equals(
+                       file_canonical.getAbsoluteFile())) {
+                return true;
+            }
+        } catch (IOException ioe) {}
+        return false;
+    }
+
+    public static byte[] readFully(File f) throws IOException {
+        InputStream inp = new FileInputStream(f);
+        // read fully into memory
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int length;
+        while ((length = inp.read(buffer)) != -1) {
+            baos.write(buffer, 0, length);
+        }
+        baos.close();
+        return baos.toByteArray();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/InvalidBundlerParamException.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal;
+
+
+public class InvalidBundlerParamException extends RuntimeException {
+    public InvalidBundlerParamException(String message) {
+        super(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/JLinkBundlerHelper.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 2015, 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.packager.internal;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.text.MessageFormat;
+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 jdk.packager.internal.builders.AbstractAppImageBuilder;
+import jdk.tools.jlink.internal.packager.AppRuntimeImageBuilder;
+
+
+public final class JLinkBundlerHelper {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+           "jdk.packager.internal.resources.JLinkBundlerHelper");
+    private static final String JRE_MODULES_FILENAME =
+            "jdk/packager/internal/resources/jre.list";
+    private static final String SERVER_JRE_MODULES_FILENAME =
+            "jdk/packager/internal/resources/server.jre.list";
+
+    private JLinkBundlerHelper() {}
+
+    @SuppressWarnings("unchecked")
+    public static final BundlerParamInfo<Boolean> DETECT_MODULES =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.detect-modules.name"),
+                    I18N.getString("param.detect-modules.description"),
+                    "detect-modules",
+                    Boolean.class,
+                    p -> Boolean.FALSE,
+                    (s, p) -> Boolean.valueOf(s));
+
+    @SuppressWarnings("unchecked")
+    public static final BundlerParamInfo<Map<String, String>> JLINK_OPTIONS =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.jlink-options.name"),
+                    I18N.getString("param.jlink-options.description"),
+                    "jlinkOptions",
+                    (Class<Map<String, String>>) (Object) Map.class,
+                    p -> Collections.emptyMap(),
+                    (s, p) -> {
+                        try {
+                            Properties props = new Properties();
+                            props.load(new StringReader(s));
+                            return new LinkedHashMap<>((Map)props);
+                        } catch (IOException e) {
+                            return new LinkedHashMap<>();
+                        }
+                    });
+
+    @SuppressWarnings("unchecked")
+    public static final BundlerParamInfo<String> JLINK_BUILDER =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.jlink-builder.name"),
+                    I18N.getString("param.jlink-builder.description"),
+                    "jlink.builder",
+                    String.class,
+                    null,
+                    (s, p) -> s);
+
+    @SuppressWarnings("unchecked")
+    public static final BundlerParamInfo<Integer> DEBUG =
+            new StandardBundlerParam<>(
+                    "",
+                    "",
+                    "-J-Xdebug",
+                    Integer.class,
+                    p -> null,
+                    (s, p) -> {
+                        return Integer.valueOf(s);
+                    });
+
+    public static String listOfPathToString(List<Path> value) {
+        String result = "";
+
+        for (Path path : value) {
+            if (result.length() > 0) {
+                result += File.pathSeparator;
+            }
+
+            result += path.toString();
+        }
+
+        return result;
+    }
+
+    public static String setOfStringToString(Set<String> value) {
+        String result = "";
+
+        for (String element : value) {
+            if (result.length() > 0) {
+                result += ",";
+            }
+
+            result += element;
+        }
+
+        return result;
+    }
+
+    public 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;
+    }
+
+    public static String getMainClass(Map<String, ? super Object> params) {
+        String result = "";
+        String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
+        if (mainModule != null)  {
+            int index = mainModule.indexOf("/");
+            if (index > 0) {
+                result = mainModule.substring(index + 1);
+            }
+        } else {
+            result = StandardBundlerParam.MAIN_CLASS.fetchFrom(params);
+        }
+
+        return result;
+    }
+
+    public static String getMainModule(Map<String, ? super Object> params) {
+        String result = "";
+        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;
+    }
+
+    public static String getJDKVersion(Map<String, ? super Object> params) {
+        String result = "";
+        List<Path> modulePath =
+                StandardBundlerParam.MODULE_PATH.fetchFrom(params);
+        Set<String> limitModules =
+                StandardBundlerParam.LIMIT_MODULES.fetchFrom(params);
+        Path javaBasePath = findPathOfModule(modulePath, "java.base.jmod");
+        Set<String> addModules = getRedistributableModules(modulePath,
+                StandardBundlerParam.ADD_MODULES.fetchFrom(params),
+                limitModules, JRE_MODULES_FILENAME);
+
+        if (javaBasePath != null && javaBasePath.toFile().exists()) {
+            result = RedistributableModules.getModuleVersion(
+                   javaBasePath.toFile(), modulePath, addModules, limitModules);
+        }
+
+        return result;
+    }
+
+    public static Path getJDKHome(Map<String, ? super Object> params) {
+        Path result = null;
+        List<Path> modulePath =
+                StandardBundlerParam.MODULE_PATH.fetchFrom(params);
+        Path javaBasePath = findPathOfModule(modulePath, "java.base.jmod");
+
+        if (javaBasePath != null && javaBasePath.toFile().exists()) {
+            result = javaBasePath.getParent();
+
+            // 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.
+            if (result != null) {
+                boolean found = false;
+                Path bin = result.resolve("bin");
+
+                if (Files.exists(bin)) {
+                    final String exe =
+                            (Platform.getPlatform() == Platform.WINDOWS) ?
+                            ".exe" : "";
+                    Path javaExe = bin.resolve("java" + exe);
+
+                    if (Files.exists(javaExe)) {
+                        found = true;
+                    }
+                }
+
+                if (!found) {
+                    result = result.resolve(".." + File.separator + "jdk");
+                }
+            }
+        }
+
+        return result;
+    }
+
+    private static Set<String> getRedistributableModules(List<Path> modulePath,
+            Set<String> addModules, Set<String> limitModules, String filename) {
+        ModuleHelper moduleHelper = new ModuleHelper(
+                modulePath, addModules, limitModules, filename);
+        return removeInvalidModules(modulePath, moduleHelper.modules());
+    }
+
+    public 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);
+        boolean stripNativeCommands =
+                StandardBundlerParam.STRIP_NATIVE_COMMANDS.fetchFrom(params);
+        Path outputDir = imageBuilder.getRoot();
+        String excludeFileList = imageBuilder.getExcludeFileList();
+        File mainJar = getMainJar(params);
+        Module.ModuleType mainJarType = Module.ModuleType.Unknown;
+
+        if (mainJar != null) {
+            mainJarType = new Module(mainJar).getModuleType();
+        } else if (mainJar == null &&
+                StandardBundlerParam.MODULE.fetchFrom(params) == null) {
+            // user specified only main class, all jars will be on the classpath
+            mainJarType = Module.ModuleType.UnnamedJar;
+        }
+
+        // Modules
+
+        // The default for an unnamed jar is ALL_DEFAULT with the
+        // non-redistributable modules removed.
+        if (mainJarType == Module.ModuleType.UnnamedJar) {
+            addModules.add(ModuleHelper.ALL_RUNTIME);
+        } else if (mainJarType == Module.ModuleType.Unknown ||
+                mainJarType == Module.ModuleType.ModularJar) {
+            String mainModule = getMainModule(params);
+            addModules.add(mainModule);
+
+            // Error if any of the srcfiles are modular jars.
+            Set<String> modularJars =
+                    getResourceFileJarList(params, Module.JarType.ModularJar);
+
+            if (!modularJars.isEmpty()) {
+                throw new Exception(MessageFormat.format(I18N.getString(
+                        "error.srcfiles.contain.modules"),
+                        modularJars.toString()));
+            }
+        }
+
+        Set<String> redistModules = getRedistributableModules(
+                modulePath, addModules, limitModules, JRE_MODULES_FILENAME);
+        addModules.addAll(redistModules);
+
+        if (imageBuilder.getPlatformSpecificModulesFile() != null) {
+            Set<String> platformModules =
+                    RedistributableModules.getRedistributableModules(
+                modulePath, imageBuilder.getPlatformSpecificModulesFile());
+            addModules.addAll(platformModules);    
+        }
+
+        Log.info(MessageFormat.format(
+                I18N.getString("message.modules"), addModules.toString()));
+
+        if (StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            Log.info("\nECHO-MODE: Running jlink [ ");
+            Log.info("--output = " + outputDir.toString());
+            Log.info("--module-path = " + modulePath.toString());
+            Log.info("--add-modules = " + addModules.toString());
+            Log.info("--limit-modules = " + limitModules.toString());
+            Log.info("--exclude-files = " + excludeFileList);
+            Log.info("--strip-native-commands = " + stripNativeCommands);
+            Log.info(" ]\n" + outputDir.toString());
+        }
+
+        AppRuntimeImageBuilder appRuntimeBuilder = new AppRuntimeImageBuilder();
+        appRuntimeBuilder.setOutputDir(outputDir);
+        appRuntimeBuilder.setModulePath(modulePath);
+        appRuntimeBuilder.setAddModules(addModules);
+        appRuntimeBuilder.setLimitModules(limitModules);
+        appRuntimeBuilder.setExcludeFileList(excludeFileList);
+        appRuntimeBuilder.setStripNativeCommands(stripNativeCommands);
+        appRuntimeBuilder.setUserArguments(new HashMap<String,String>());
+
+        appRuntimeBuilder.build();
+        imageBuilder.prepareApplicationFiles();
+    }
+
+    public static void generateServerJre(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);
+        boolean stripNativeCommands =
+                StandardBundlerParam.STRIP_NATIVE_COMMANDS.fetchFrom(params);
+        Path outputDir = imageBuilder.getRoot();
+        addModules.add(ModuleHelper.ALL_RUNTIME);
+        Set<String> redistModules = getRedistributableModules(modulePath,
+                addModules, limitModules, SERVER_JRE_MODULES_FILENAME);
+        addModules.addAll(redistModules);
+
+        if (imageBuilder.getPlatformSpecificModulesFile() != null) {
+            Set<String> platformModules =
+                    RedistributableModules.getRedistributableModules(
+                    modulePath, imageBuilder.getPlatformSpecificModulesFile());
+            addModules.addAll(platformModules);    
+        }
+
+        Log.info(MessageFormat.format(
+                I18N.getString("message.modules"), addModules.toString()));
+
+        if (StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            Log.info("\nECHO-MODE: Running jlink [ ");
+            Log.info("--output = " + outputDir.toString());
+            Log.info("--module-path = " + modulePath.toString());
+            Log.info("--add-modules = " + addModules.toString());
+            Log.info("--limit-modules = " + limitModules.toString());
+            Log.info("--strip-native-commands = " + stripNativeCommands);
+            Log.info(" ]\n" + outputDir.toString());
+        }
+
+        AppRuntimeImageBuilder appRuntimeBuilder = new AppRuntimeImageBuilder();
+        appRuntimeBuilder.setOutputDir(outputDir);
+        appRuntimeBuilder.setModulePath(modulePath);
+        appRuntimeBuilder.setAddModules(addModules);
+        appRuntimeBuilder.setLimitModules(limitModules);
+        appRuntimeBuilder.setStripNativeCommands(stripNativeCommands);
+        appRuntimeBuilder.setExcludeFileList("");
+        appRuntimeBuilder.setUserArguments(new HashMap<String,String>());
+
+        appRuntimeBuilder.build();
+        imageBuilder.prepareServerJreFiles();
+    }
+
+    // Returns the path to the JDK modules in the user defined module path.
+    public static Path findPathOfModule(
+            List<Path> modulePath, String moduleName) {
+        Path result = null;
+
+        for (Path path : modulePath) {
+            Path moduleNamePath = path.resolve(moduleName);
+
+            if (Files.exists(moduleNamePath)) {
+                result = path;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    private static Set<String> getResourceFileJarList(
+            Map<String, ? super Object> params, Module.JarType Query) {
+        Set<String> files = new LinkedHashSet();
+
+        String srcdir = StandardBundlerParam.SOURCE_DIR.fetchFrom(params);
+
+        for (RelativeFileSet appResources :
+                StandardBundlerParam.APP_RESOURCES_LIST.fetchFrom(params)) {
+            for (String resource : appResources.getIncludedFiles()) {
+                if (resource.endsWith(".jar")) {
+                    String filename = srcdir + File.separator + resource;
+
+                    switch (Query) {
+                        case All: {
+                            files.add(filename);
+                            break;
+                        }
+                        case ModularJar: {
+                            Module module = new Module(new File(filename));
+
+                            if (module.getModuleType() ==
+                                    Module.ModuleType.ModularJar) {
+                                files.add(filename);
+                            }
+                            break;
+                        }
+                        case UnnamedJar: {
+                            Module module = new Module(new File(filename));
+
+                            if (module.getModuleType() ==
+                                    Module.ModuleType.UnnamedJar) {
+                                files.add(filename);
+                            }
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        return files;
+    }
+
+    private static Set<String> removeInvalidModules(
+            List<Path> modulePath, Set<String> modules) {
+        Set<String> result = new LinkedHashSet();
+        ModuleManager mm = new ModuleManager(modulePath);
+        List<Module> lmodules =
+                mm.getModules(EnumSet.of(ModuleManager.SearchType.ModularJar,
+                        ModuleManager.SearchType.Jmod,
+                        ModuleManager.SearchType.ExplodedModule));
+
+        HashMap<String, Module> validModules = new HashMap<>();
+
+        for (Module module : lmodules) {
+            validModules.put(module.getModuleName(), module);
+        }
+
+        for (String name : modules) {
+            if (validModules.containsKey(name)) {
+                result.add(name);
+            }
+            else {
+                Log.info(MessageFormat.format(
+                        I18N.getString("warning.module.does.not.exist"), name));
+            }
+        }
+
+        return result;
+    }
+
+    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 redistributable runtime modules".
+        public static final String ALL_RUNTIME = "ALL-RUNTIME";
+
+        private final Set<String> modules = new HashSet<>();
+        private enum Macros {None, AllModulePath, AllRuntime}
+
+        public ModuleHelper(List<Path> paths, Set<String> roots,
+                Set<String> limitMods, String filename) {
+            Macros macro = Macros.None;
+
+            for (Iterator<String> iterator = roots.iterator();
+                    iterator.hasNext();) {
+                String module = iterator.next();
+
+                switch (module) {
+                    case ALL_MODULE_PATH:
+                        iterator.remove();
+                        macro = Macros.AllModulePath;
+                        break;
+                    case ALL_RUNTIME:
+                        iterator.remove();
+                        macro = Macros.AllRuntime;
+                        break;
+                    default:
+                        this.modules.add(module);
+                }
+            }
+
+            switch (macro) {
+                case AllModulePath:
+                    this.modules.addAll(getModuleNamesFromPath(paths));
+                    break;
+                case AllRuntime:
+                    Set<String> m =
+                            RedistributableModules.getRedistributableModules(
+                            paths, filename);
+
+                    if (m != null) {
+                        this.modules.addAll(m);
+                    }
+
+                    break;
+            }
+        }
+
+        public Set<String> modules() {
+            return modules;
+        }
+
+        private static Set<String> getModuleNamesFromPath(List<Path> Value) {
+                Set<String> result = new LinkedHashSet();
+                ModuleManager mm = new ModuleManager(Value);
+                List<Module> modules =
+                        mm.getModules(
+                                EnumSet.of(ModuleManager.SearchType.ModularJar,
+                                ModuleManager.SearchType.Jmod,
+                                ModuleManager.SearchType.ExplodedModule));
+
+                for (Module module : modules) {
+                    result.add(module.getModuleName());
+                }
+
+                return result;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/JavaPackagerToolProvider.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017, 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.packager.internal;
+
+import java.io.PrintWriter;
+import java.util.spi.ToolProvider;
+
+public class JavaPackagerToolProvider implements ToolProvider {
+
+    public String name() {
+        return "javapackager";
+    }
+
+    public synchronized int run(
+            PrintWriter out, PrintWriter err, String... args) {
+        try {
+            jdk.packager.Main.run(out, err, args);
+        } catch (Exception ignored) {
+            return 1;
+        }
+        return 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/JreUtils.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+
+public class JreUtils {
+
+    public static class Rule {
+        String regex;
+        boolean includeRule;
+        Type type;
+        enum Type {SUFFIX, PREFIX, SUBSTR, REGEX}
+
+        private Rule(String regex, boolean includeRule, Type type) {
+            this.regex = regex;
+            this.type = type;
+            this.includeRule = includeRule;
+        }
+
+        boolean match(String str) {
+            if (type == Type.SUFFIX) {
+                return str.endsWith(regex);
+            }
+            if (type == Type.PREFIX) {
+                return str.startsWith(regex);
+            }
+            if (type == Type.SUBSTR) {
+                return str.contains(regex);
+            }
+            return str.matches(regex);
+        }
+
+        boolean treatAsAccept() {return includeRule;}
+
+        public static Rule suffix(String s) {
+            return new Rule(s, true, Type.SUFFIX);
+        }
+        public static Rule suffixNeg(String s) {
+            return new Rule(s, false, Type.SUFFIX);
+        }
+        static Rule prefix(String s) {
+            return new Rule(s, true, Type.PREFIX);
+        }
+        public static Rule prefixNeg(String s) {
+            return new Rule(s, false, Type.PREFIX);
+        }
+        static Rule substr(String s) {
+            return new Rule(s, true, Type.SUBSTR);
+        }
+        public static Rule substrNeg(String s) {
+            return new Rule(s, false, Type.SUBSTR);
+        }
+    }
+
+    public static boolean shouldExclude(File baseDir, File f, Rule ruleset[]) {
+        if (ruleset == null) {
+            return false;
+        }
+
+        String fname = f.getAbsolutePath().toLowerCase().substring(
+                baseDir.getAbsolutePath().length());
+        // first rule match defines the answer
+        for (Rule r: ruleset) {
+            if (r.match(fname)) {
+                return !r.treatAsAccept();
+            }
+        }
+        // default is include
+        return false;
+    }
+
+    public static void walk(File base, File root,
+            Rule ruleset[], Set<File> files) {
+        walk(base, root, ruleset, files, false);
+    }
+
+    public static void walk(File base, File root, Rule ruleset[],
+            Set<File> files, boolean acceptSymlinks) {
+        if (!root.isDirectory()) {
+            if (root.isFile()) {
+                files.add(root);
+            }
+            return;
+        }
+
+        File[] lst = root.listFiles();
+        if (lst != null) {
+            for (File f : lst) {
+                if ((acceptSymlinks || IOUtils.isNotSymbolicLink(f)) &&
+                        !shouldExclude(base, f, ruleset)) {
+                    if (f.isDirectory()) {
+                        walk(base, f, ruleset, files, acceptSymlinks);
+                    } else if (f.isFile()) {
+                        // add to list
+                        files.add(f);
+                    }
+                }
+            }
+        }
+    }
+
+    public static RelativeFileSet extractJreAsRelativeFileSet(String root,
+            JreUtils.Rule[] ruleset) {
+        return extractJreAsRelativeFileSet(root, ruleset, false);
+    }
+
+    public static RelativeFileSet extractJreAsRelativeFileSet(String root,
+            JreUtils.Rule[] ruleset, boolean acceptSymlinks) {
+        if (root.isEmpty()) {
+            return null;
+        }
+
+        File baseDir = new File(root);
+        Set<File> lst = new HashSet<>();
+        walk(baseDir, baseDir, ruleset, lst, acceptSymlinks);
+
+        return new RelativeFileSet(baseDir, lst);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/Log.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2011, 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.packager.internal;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+
+public class Log {
+    public static class Logger {
+        private boolean verbose = false;
+        private PrintWriter out = null;
+        private PrintWriter err = null;
+
+        public Logger(boolean v) {
+            verbose = v;
+        }
+
+        public void setVerbose(boolean v) {
+            verbose = v;
+        }
+
+        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 infof(String format, Object... args) {
+            if (out != null) {
+                out.printf(format, args);
+            } else {
+                System.out.printf(format, args);
+            }
+        }
+
+        public void error(String msg) {
+            if (err != null) {
+                err.println(msg);
+            } else {
+                System.err.println(msg);
+            }
+        }
+
+        public void verbose(Throwable t) {
+            if (out != null && (Log.debug || verbose)) {
+                t.printStackTrace(out);
+            } else if (Log.debug || verbose) {
+                t.printStackTrace(System.out);
+            }
+        }
+
+        public void verbose(String msg) {
+            if (out != null && (Log.debug || verbose || Arguments.echoMode())) {
+                out.println(msg);
+            } else if (Log.debug || verbose || Arguments.echoMode()) {
+                System.out.println(msg);
+            }
+        }
+
+        public void debug(String msg) {
+            if (out != null && Log.debug) {
+                out.println(msg);
+            } else if (Log.debug) {
+                System.out.println(msg);
+            }
+        }
+    }
+
+    private static Logger delegate = null;
+    private static boolean debug =
+            "true".equals(System.getenv("JPACKAGER_DEBUG"));
+
+    public static void setLogger(Logger l) {
+        delegate = l;
+        if (l == null) {
+            delegate = new Logger(false);
+        }
+    }
+
+    public static Logger getLogger() {
+        return delegate;
+    }
+
+    public static void flush() {
+        if (delegate != null) {
+            delegate.flush();
+        }
+    }
+
+    public static void info(String msg) {
+        if (delegate != null) {
+           delegate.info(msg);
+        }
+    }
+
+    public static void infof(String format, Object... args) {
+        if (delegate != null) {
+           delegate.infof(format, args);
+        }
+    }
+
+    public static void error(String msg) {
+        if (delegate != null) {
+            delegate.error(msg);
+        }
+    }
+
+    public static void verbose(String msg) {
+        if (delegate != null) {
+           delegate.verbose(msg);
+        }
+    }
+
+    public static void verbose(Throwable t) {
+        if (delegate != null) {
+           delegate.verbose(t);
+        }
+    }
+
+    public static void debug(String msg) {
+        if (delegate != null) {
+           delegate.debug(msg);
+        }
+    }
+
+    public static void debug(RuntimeException re) {
+        debug((Throwable) re);
+    }
+
+    public static void debug(Throwable t) {
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            try (PrintStream ps = new PrintStream(baos)) {
+                t.printStackTrace(ps);
+            }
+            debug(baos.toString());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static boolean isDebug() {
+        return debug;
+    }
+
+    public static void setDebug(boolean debug) {
+        Log.debug = debug;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/Module.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2016, 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.packager.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;
+
+
+public final class Module {
+    private final String filename;
+    private final ModuleType moduleType;
+
+    public enum JarType {All, UnnamedJar, ModularJar}
+    public enum ModuleType {
+            Unknown, UnnamedJar, ModularJar, Jmod, ExplodedModule}
+
+    public Module(File AFile) {
+        super();
+        filename = AFile.getPath();
+        moduleType = getModuleType(AFile);
+    }
+
+    public String getModuleName() {
+        File file = new File(getFileName());
+        // do not try to remove extension for directories
+        return moduleType == ModuleType.ExplodedModule ?
+                file.getName() : getFileWithoutExtension(file.getName());
+    }
+
+    public String getFileName() {
+        return filename;
+    }
+
+    public ModuleType getModuleType() {
+        return moduleType;
+    }
+
+    private static ModuleType getModuleType(File AFile) {
+        ModuleType result = ModuleType.Unknown;
+        String filename = AFile.getAbsolutePath();
+
+        if (AFile.isFile()) {
+            if (filename.endsWith(".jmod")) {
+                result = ModuleType.Jmod;
+            }
+            else if (filename.endsWith(".jar")) {
+                JarType status = isModularJar(filename);
+
+                if (status == JarType.ModularJar) {
+                    result = ModuleType.ModularJar;
+                }
+                else if (status == JarType.UnnamedJar) {
+                    result = ModuleType.UnnamedJar;
+                }
+            }
+        }
+        else if (AFile.isDirectory()) {
+            File moduleInfo = new File(
+                    filename + File.separator + "module-info.class");
+
+            if (moduleInfo.exists()) {
+                result = ModuleType.ExplodedModule;
+            }
+        }
+
+        return result;
+    }
+
+    private static JarType isModularJar(String FileName) {
+        JarType result = JarType.All;
+
+        try {
+            ZipInputStream zip =
+                    new ZipInputStream(new FileInputStream(FileName));
+            result = JarType.UnnamedJar;
+
+            try {
+                for (ZipEntry entry = zip.getNextEntry(); entry != null;
+                        entry = zip.getNextEntry()) {
+                    if (entry.getName().matches("module-info.class")) {
+                        result = JarType.ModularJar;
+                        break;
+                    }
+                }
+
+                zip.close();
+            } catch (IOException ex) {
+            }
+        } catch (FileNotFoundException e) {
+        }
+
+        return result;
+    }
+
+    private static String getFileWithoutExtension(String FileName) {
+        return FileName.replaceFirst("[.][^.]+$", "");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/ModuleManager.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016, 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.packager.internal;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+
+public final class ModuleManager {
+    private final List<String> folders = new ArrayList();
+
+    public enum SearchType {UnnamedJar, ModularJar, Jmod, ExplodedModule}
+
+    public ModuleManager(String folders) {
+        super();
+        String lfolders = folders.replaceAll("^\"|\"$", "");
+        List<Path> paths = new ArrayList();
+
+        for (String folder :
+                Arrays.asList(lfolders.split(File.pathSeparator))) {
+            File file = new File(folder);
+            paths.add(file.toPath());
+        }
+
+        initialize(paths);
+    }
+
+    public ModuleManager(List<Path> Paths) {
+        super();
+        initialize(Paths);
+    }
+
+    private void initialize(List<Path> Paths) {
+        for (Path path : Paths) {
+            folders.add(path.toString().replaceAll("^\"|\"$", ""));
+        }
+    }
+
+    public List<Module> getModules() {
+        return getModules(EnumSet.of(SearchType.UnnamedJar,
+                SearchType.ModularJar, SearchType.Jmod,
+                SearchType.ExplodedModule));
+    }
+
+    public List<Module> getModules(EnumSet<SearchType> Search) {
+        List<Module> result = new ArrayList();
+
+        for (String folder : folders) {
+            result.addAll(getAllModulesInDirectory(folder, Search));
+        }
+
+        return result;
+    }
+
+    private static List<Module> getAllModulesInDirectory(String Folder,
+            EnumSet<SearchType> Search) {
+        List<Module> result = new ArrayList();
+        File lfolder = new File(Folder);
+        File[] files = lfolder.listFiles();
+
+        for (File file : files) {
+            Module module = new Module(file);
+
+            switch (module.getModuleType()) {
+                case Unknown:
+                    break;
+                case UnnamedJar:
+                    if (Search.contains(SearchType.UnnamedJar)) {
+                        result.add(module);
+                    }
+                    break;
+                case ModularJar:
+                    if (Search.contains(SearchType.ModularJar)) {
+                        result.add(module);
+                    }
+                    break;
+                case Jmod:
+                    if (Search.contains(SearchType.Jmod)) {
+                        result.add(module);
+                    }
+                    break;
+                case ExplodedModule:
+                    if (Search.contains(SearchType.ExplodedModule)) {
+                        result.add(module);
+                    }
+                    break;
+            }
+        }
+
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/PackagerException.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011, 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.packager.internal;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+
+public class PackagerException extends Exception {
+    private static final ResourceBundle bundle =
+            ResourceBundle.getBundle("jdk.packager.internal.resources.Bundle");
+
+    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.packager/share/classes/jdk/packager/internal/Param.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011, 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.packager.internal;
+
+
+public class Param {
+    String name;
+    String value;
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/Platform.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2016, 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.packager.internal;
+
+import java.util.regex.Pattern;
+
+/**
+ * Use <code>Platform</code> to detect the operating system
+ * that is currently running.
+ *
+ * Example:
+ *
+ *  Platform platform = Platform.getPlatform();
+ *
+ *  switch(platform) {
+ *    case Platform.MAC: {
+ *      //TODO Do something
+ *      break;
+ *    }
+ *    case Platform.WINDOWS:
+ *    case Platform.LINUX: {
+ *      //TODO Do something else
+ *    }
+ *  }
+ *
+ */
+public enum Platform {UNKNOWN, WINDOWS, LINUX, MAC, SOLARIS;
+    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 if (os.indexOf("sunos") >= 0 || os.indexOf("solaris") >= 0) {
+            platform = Platform.SOLARIS;
+        }
+        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() {}
+
+    public static Platform getPlatform() {
+        return platform;
+    }
+
+    public static int getMajorVersion() {
+        return majorVersion;
+    }
+
+    public static int getMinorVersion() {
+        return minorVersion;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/RedistributableModules.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2015, 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.packager.internal;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.Optional;
+
+import jdk.tools.jlink.internal.packager.AppRuntimeImageBuilder;
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.lang.module.ModuleReader;
+
+import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+
+public final class RedistributableModules {
+    private static final String JDK_PACKAGER_MODULE = "jdk.packager";
+
+    private RedistributableModules() {}
+
+    public static String stripComments(String line) {
+        String result = line.trim();
+        int i = result.indexOf(";");
+
+        if (i >= 0) {
+          result = result.substring(0, i);
+          result = result.trim();
+        }
+
+        return result;
+    }
+
+    public static Set<String> getRedistributableModules(List<Path> modulePath,
+            String filename) {
+        Set<String> result = null;
+
+        Set<String> addModules = new HashSet<>();
+        Set<String> limitModules = new HashSet<>();
+        ModuleFinder finder = AppRuntimeImageBuilder.moduleFinder(
+                modulePath, addModules, limitModules);
+        Optional<ModuleReference> mref = finder.find(JDK_PACKAGER_MODULE);
+
+        if (mref.isPresent()) {
+            ModuleReader reader = null;
+
+            try {
+                reader = mref.get().open();
+            } catch (NoSuchElementException | IOException ex) {
+            }
+
+            if (reader != null) {
+                Optional<InputStream> stream = null;
+
+                try {
+                    stream = reader.open(filename);
+                } catch (IOException ex) {
+                }
+
+                if (stream != null) {
+                    if (stream.isPresent()) {
+                        BufferedReader br = null;
+
+                        try {
+                            br = new BufferedReader(new InputStreamReader(
+                                    stream.get(), "UTF-8"));
+                        } catch (UnsupportedEncodingException ex) {
+                        }
+
+                        if (br != null) {
+                            result = new LinkedHashSet();
+                            String line;
+
+                            try {
+                                while ((line = br.readLine()) != null) {
+                                    String module = stripComments(line);
+
+                                    if (!module.isEmpty()) {
+                                        result.add(module);
+                                    }
+                                }
+                            } catch (IOException ex) {
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+
+    public static String getModuleVersion(File moduleFile,
+            List<Path> modulePath, Set<String> addModules,
+            Set<String> limitModules) {
+        String result = "";
+
+        Module module = new Module(moduleFile);
+        ModuleFinder finder = AppRuntimeImageBuilder.moduleFinder(modulePath,
+                addModules, limitModules);
+        Optional<ModuleReference> mref = finder.find(module.getModuleName());
+
+        if (mref.isPresent()) {
+            ModuleDescriptor descriptor = mref.get().descriptor();
+
+            if (descriptor != null) {
+                Optional<ModuleDescriptor.Version> version =
+                        descriptor.version();
+
+                if (version.isPresent()) {
+                    result = version.get().toString();
+                }
+            }
+        }
+
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/RelativeFileSet.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal;
+
+import java.io.File;
+
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+
+public class RelativeFileSet {
+
+    public enum Type {
+        UNKNOWN, jnlp, jar, nativelib, icon, license, data
+    }
+
+    private Type type = Type.UNKNOWN;
+    private String mode;
+    private String os;
+    private String arch;
+
+    private File basedir;
+    private Set<String> files = new LinkedHashSet<>();
+
+    public RelativeFileSet(RelativeFileSet copy) {
+        type = copy.type;
+        mode = copy.mode;
+        os = copy.os;
+        arch = copy.arch;
+        basedir = copy.basedir;
+        files = new LinkedHashSet<>(copy.files);
+    }
+
+    public 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 javapackager case
+                this.files.add(absolute.substring(baseAbsolute.length()+1));
+            }
+        }
+    }
+
+    public void upshift() {
+        String root = basedir.getName();
+        basedir = basedir.getParentFile();
+        Set<String> newFiles = new LinkedHashSet<>();
+        for (String s : files) {
+            newFiles.add(root + File.separator + s);
+        }
+        files = newFiles;
+    }
+
+    public RelativeFileSet(File base, Set<File> files) {
+        this(base, (Collection<File>) files);
+    }
+
+    public boolean contains(String[] requiredFiles) {
+        boolean result = true;
+
+        for(String fname: requiredFiles) {
+            if (!files.contains(fname)) {
+                Log.debug("  Runtime does not contain [" + fname + "]");
+                result = false;
+            }
+        }
+
+        return result;
+    }
+
+    public boolean contains(String requiredFile) {
+        if (files.contains(requiredFile)) {
+            return true;
+        } else {
+            Log.debug("  Runtime does not contain [" + requiredFile + "]");
+            return false;
+        }
+    }
+
+    public File getBaseDirectory() {
+        return basedir;
+    }
+
+    public Set<String> getIncludedFiles() {
+        return files;
+    }
+
+    public void dump() {
+        Log.verbose("\n=========\nBasedir: " + basedir + "\n");
+        for (String fname : files) {
+            Log.verbose("  " + fname);
+        }
+        Log.verbose("\n========");
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public void setType(Type type) {
+        this.type = type;
+    }
+
+    public String getMode() {
+        return mode;
+    }
+
+    public void setMode(String mode) {
+        this.mode = mode;
+    }
+
+    public String getOs() {
+        return os;
+    }
+
+    public void setOs(String os) {
+        this.os = os;
+    }
+
+    public String getArch() {
+        return arch;
+    }
+
+    public void setArch(String arch) {
+        this.arch = arch;
+    }
+
+    @Override
+    public String toString() {
+        return "RelativeFileSet{basedir:" + basedir + ", files:" + files + "}";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/SecondaryLauncherArguments.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 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.packager.internal;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.io.File;
+import jdk.packager.internal.Arguments.CLIOptions;
+
+public class SecondaryLauncherArguments {
+
+    private final String filename;
+    private Map<String, String> allArgs;
+    private Map<String, ? super Object> bundleParams;
+
+    public SecondaryLauncherArguments(String filename) {
+        this.filename = filename;
+    }
+
+    private void initLauncherMap() {
+        if (bundleParams != null) {
+            return;
+        }
+        
+        allArgs = Arguments.getPropertiesFromFile(filename);
+        
+        bundleParams = new HashMap<>();
+        String mainClass = getOptionValue(CLIOptions.APPCLASS);
+        String module = getOptionValue(CLIOptions.MODULE);
+
+        if (module != null && mainClass != null) {
+            putUnlessNull(bundleParams, Arguments.CLIOptions.MODULE.getId(),
+                    module + "/" + mainClass);
+        } else if (module != null) {
+            putUnlessNull(bundleParams, Arguments.CLIOptions.MODULE.getId(),
+                    module);
+        } else if (mainClass != null) {
+            putUnlessNull(bundleParams, Arguments.CLIOptions.APPCLASS.getId(),
+                    mainClass); 
+        }
+        
+        putUnlessNull(bundleParams, Arguments.CLIOptions.NAME.getId(),
+                getOptionValue(CLIOptions.NAME));
+        putUnlessNull(bundleParams, Arguments.CLIOptions.VERSION.getId(),
+                getOptionValue(CLIOptions.VERSION));
+        
+        // 3 boolean values:
+        putUnlessNull(bundleParams, Arguments.CLIOptions.WIN_MENU_HINT.getId(),
+                getOptionValue(CLIOptions.WIN_MENU_HINT));
+        putUnlessNull(bundleParams,
+                Arguments.CLIOptions.WIN_SHORTCUT_HINT.getId(),
+                getOptionValue(CLIOptions.WIN_SHORTCUT_HINT));
+        putUnlessNull(bundleParams, Arguments.CLIOptions.SINGLETON.getId(),
+                getOptionValue(CLIOptions.SINGLETON));
+
+        String value = getOptionValue(CLIOptions.ICON);
+        putUnlessNull(bundleParams, Arguments.CLIOptions.ICON.getId(),
+                (value == null) ? null : new File(value));
+        
+        String argumentStr = getOptionValue(CLIOptions.ARGUMENTS);
+        putUnlessNullOrEmpty(bundleParams,
+                CLIOptions.ARGUMENTS.getId(),
+                Arguments.getArgumentList(argumentStr));
+
+        String jvmargsStr = getOptionValue(CLIOptions.JVM_ARGS);
+        putUnlessNullOrEmpty(bundleParams,
+                CLIOptions.JVM_ARGS.getId(),
+                Arguments.getArgumentList(jvmargsStr));
+
+        String jvmUserArgsStr = getOptionValue(CLIOptions.USER_JVM_ARGS);
+        putUnlessNullOrEmpty(bundleParams,
+                CLIOptions.USER_JVM_ARGS.getId(),
+                Arguments.getArgumentMap(jvmUserArgsStr));
+    }
+
+    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;
+    }
+
+    public 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);
+        }
+    }
+
+    private void putUnlessNullOrEmpty(Map<String, ? super Object> params,
+            String param, Collection value) {
+        if (value != null && !value.isEmpty()) {
+            params.put(param, value);
+        }
+    }
+
+    private void putUnlessNullOrEmpty(Map<String, ? super Object> params,
+            String param, Map value) {
+        if (value != null && !value.isEmpty()) {
+            params.put(param, value);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/StandardBundlerParam.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,933 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal;
+
+import jdk.packager.internal.bundlers.BundleParams;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+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.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+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.regex.Pattern;
+import java.util.stream.Collectors;
+import jdk.packager.internal.builders.AbstractAppImageBuilder;
+
+public class StandardBundlerParam<T> extends BundlerParamInfo<T> {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.StandardBundlerParam");
+    private static final String JAVABASEJMOD = "java.base.jmod";
+
+    public StandardBundlerParam(String name, String description, String id,
+            Class<T> valueType,
+            Function<Map<String, ? super Object>, T> defaultValueFunction,
+            BiFunction<String, Map<String, ? super Object>, T> stringConverter)
+    {
+        this.name = name;
+        this.description = description;
+        this.id = id;
+        this.valueType = valueType;
+        this.defaultValueFunction = defaultValueFunction;
+        this.stringConverter = stringConverter;
+    }
+
+    public static final StandardBundlerParam<RelativeFileSet> APP_RESOURCES =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.app-resources.name"),
+                    I18N.getString("param.app-resource.description"),
+                    BundleParams.PARAM_APP_RESOURCES,
+                    RelativeFileSet.class,
+                    null, // no default.  Required parameter
+                    null  // no string translation,
+                          // tool must provide complex type
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final
+            StandardBundlerParam<List<RelativeFileSet>> APP_RESOURCES_LIST =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.app-resources-list.name"),
+                    I18N.getString("param.app-resource-list.description"),
+                    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
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final StandardBundlerParam<String> SOURCE_DIR =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.source-dir.name"),
+                    I18N.getString("param.source-dir.description"),
+                    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;
+                        }
+                    }
+            );
+
+    public static final StandardBundlerParam<List<File>> SOURCE_FILES =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.source-files.name"),
+                    I18N.getString("param.source-files.description"),
+                    Arguments.CLIOptions.FILES.getId(),
+                    (Class<List<File>>) (Object) List.class,
+                    p -> null,
+                    (s, p) -> null
+            );
+
+    // note that each bundler is likely to replace this one with
+    // their own converter
+    public static final StandardBundlerParam<RelativeFileSet> MAIN_JAR =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.main-jar.name"),
+                    I18N.getString("param.main-jar.description"),
+                    Arguments.CLIOptions.MAIN_JAR.getId(),
+                    RelativeFileSet.class,
+                    params -> {
+                        extractMainClassInfoFromAppResources(params);
+                        return (RelativeFileSet) params.get("mainJar");
+                    },
+                    (s, p) -> getMainJar(s, p)
+            );
+
+    // TODO: remove it
+    public static final StandardBundlerParam<String> CLASSPATH =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.classpath.name"),
+                    I18N.getString("param.classpath.description"),
+                    "classpath",
+                    String.class,
+                    params -> {
+                        extractMainClassInfoFromAppResources(params);
+                        String cp = (String) params.get("classpath");
+                        return cp == null ? "" : cp;
+                    },
+                    (s, p) -> s.replace(File.pathSeparator, " ")
+            );
+
+    public static final StandardBundlerParam<String> MAIN_CLASS =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.main-class.name"),
+                    I18N.getString("param.main-class.description"),
+                    Arguments.CLIOptions.APPCLASS.getId(),
+                    String.class,
+                    params -> {
+                        if (Arguments.CREATE_JRE_INSTALLER.fetchFrom(params)) {
+                            return null;
+                        } 
+                        extractMainClassInfoFromAppResources(params);
+                        String s = (String) params.get(
+                                BundleParams.PARAM_APPLICATION_CLASS);
+                        if (s == null) {
+                            s = JLinkBundlerHelper.getMainClass(params);
+                        }
+                        return s;
+                    },
+                    (s, p) -> s
+            );
+
+    public static final StandardBundlerParam<String> APP_NAME =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.app-name.name"),
+                    I18N.getString("param.app-name.description"),
+                    Arguments.CLIOptions.NAME.getId(),
+                    String.class,
+                    params -> {
+                        String s = MAIN_CLASS.fetchFrom(params);
+                        if (s == null) return null;
+
+                        int idx = s.lastIndexOf(".");
+                        if (idx >= 0) {
+                            return s.substring(idx+1);
+                        }
+                        return s;
+                    },
+                    (s, p) -> s
+            );
+
+    private static Pattern TO_FS_NAME = Pattern.compile("\\s|[\\\\/?:*<>|]");
+            // keep out invalid/undesireable filename characters
+
+    public static final StandardBundlerParam<String> APP_FS_NAME =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.app-fs-name.name"),
+                    I18N.getString("param.app-fs-name.description"),
+                    "name.fs",
+                    String.class,
+                    params -> TO_FS_NAME.matcher(
+                            APP_NAME.fetchFrom(params)).replaceAll(""),
+                    (s, p) -> s
+            );
+
+    public static final StandardBundlerParam<File> ICON =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.icon-file.name"),
+                    I18N.getString("param.icon-file.description"),
+                    Arguments.CLIOptions.ICON.getId(),
+                    File.class,
+                    params -> null,
+                    (s, p) -> new File(s)
+            );
+
+    public static final StandardBundlerParam<String> VENDOR =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.vendor.name"),
+                    I18N.getString("param.vendor.description"),
+                    Arguments.CLIOptions.VENDOR.getId(),
+                    String.class,
+                    params -> I18N.getString("param.vendor.default"),
+                    (s, p) -> s
+            );
+
+    public static final StandardBundlerParam<String> CATEGORY =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.category.name"),
+                    I18N.getString("param.category.description"),
+                   Arguments.CLIOptions.CATEGORY.getId(),
+                    String.class,
+                    params -> I18N.getString("param.category.default"),
+                    (s, p) -> s
+            );
+
+    public static final StandardBundlerParam<String> DESCRIPTION =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.description.name"),
+                    I18N.getString("param.description.description"),
+                    Arguments.CLIOptions.DESCRIPTION.getId(),
+                    String.class,
+                    params -> params.containsKey(APP_NAME.getID())
+                            ? APP_NAME.fetchFrom(params)
+                            : I18N.getString("param.description.default"),
+                    (s, p) -> s
+            );
+
+    public static final StandardBundlerParam<String> COPYRIGHT =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.copyright.name"),
+                    I18N.getString("param.copyright.description"),
+                    Arguments.CLIOptions.COPYRIGHT.getId(),
+                    String.class,
+                    params -> MessageFormat.format(I18N.getString(
+                            "param.copyright.default"), new Date()),
+                    (s, p) -> s
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final StandardBundlerParam<List<String>> ARGUMENTS =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.arguments.name"),
+                    I18N.getString("param.arguments.description"),
+                    Arguments.CLIOptions.ARGUMENTS.getId(),
+                    (Class<List<String>>) (Object) List.class,
+                    params -> Collections.emptyList(),
+                    (s, p) -> splitStringWithEscapes(s)
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final StandardBundlerParam<List<String>> JVM_OPTIONS =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.jvm-options.name"),
+                    I18N.getString("param.jvm-options.description"),
+                    Arguments.CLIOptions.JVM_ARGS.getId(),
+                    (Class<List<String>>) (Object) List.class,
+                    params -> Collections.emptyList(),
+                    (s, p) -> Arrays.asList(s.split("\n\n"))
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final
+            StandardBundlerParam<Map<String, String>> JVM_PROPERTIES =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.jvm-system-properties.name"),
+                    I18N.getString("param.jvm-system-properties.description"),
+                    "jvmProperties",
+                    (Class<Map<String, String>>) (Object) Map.class,
+                    params -> Collections.emptyMap(),
+                    (s, params) -> {
+                        Map<String, String> map = new HashMap<>();
+                        try {
+                            Properties p = new Properties();
+                            p.load(new StringReader(s));
+                            for (Map.Entry<Object,
+                                    Object> entry : p.entrySet()) {
+                                map.put((String)entry.getKey(),
+                                        (String)entry.getValue());
+                            }
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                        return map;
+                    }
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final
+            StandardBundlerParam<Map<String, String>> USER_JVM_OPTIONS =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.user-jvm-options.name"),
+                    I18N.getString("param.user-jvm-options.description"),
+                    Arguments.CLIOptions.USER_JVM_ARGS.getId(),
+                    (Class<Map<String, String>>) (Object) Map.class,
+                    params -> Collections.emptyMap(),
+                    (s, params) -> {
+                        Map<String, String> map = new HashMap<>();
+                        try {
+                            Properties p = new Properties();
+                            p.load(new StringReader(s));
+                            for (Map.Entry<Object, Object> entry :
+                                    p.entrySet()) {
+                                map.put((String)entry.getKey(),
+                                        (String)entry.getValue());
+                            }
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                        return map;
+                    }
+            );
+
+    public static final StandardBundlerParam<String> TITLE =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.title.name"),
+                    I18N.getString("param.title.description"),
+                    BundleParams.PARAM_TITLE,
+                    String.class,
+                    APP_NAME::fetchFrom,
+                    (s, p) -> s
+            );
+
+    // note that each bundler is likely to replace this one with
+    // their own converter
+    public static final StandardBundlerParam<String> VERSION =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.version.name"),
+                    I18N.getString("param.version.description"),
+                    Arguments.CLIOptions.VERSION.getId(),
+                    String.class,
+                    params -> I18N.getString("param.version.default"),
+                    (s, p) -> s
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final StandardBundlerParam<List<String>> LICENSE_FILE =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.license-file.name"),
+                    I18N.getString("param.license-file.description"),
+                    Arguments.CLIOptions.LICENSE_FILE.getId(),
+                    (Class<List<String>>)(Object)List.class,
+                    params -> Collections.<String>emptyList(),
+                    (s, p) -> Arrays.asList(s.split(","))
+            );
+
+    public static final StandardBundlerParam<File> BUILD_ROOT =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.build-root.name"),
+                    I18N.getString("param.build-root.description"),
+                    Arguments.CLIOptions.BUILD_ROOT.getId(),
+                    File.class,
+                    params -> {
+                        try {
+                            return Files.createTempDirectory(
+                                    "jdk.packager").toFile();
+                        } catch (IOException ioe) {
+                            return null;
+                        }
+                    },
+                    (s, p) -> new File(s)
+            );
+
+    public static final StandardBundlerParam<String> IDENTIFIER =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.identifier.name"),
+                    I18N.getString("param.identifier.description"),
+                    Arguments.CLIOptions.IDENTIFIER.getId(),
+                    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
+            );
+
+    public static final StandardBundlerParam<String> PREFERENCES_ID =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.preferences-id.name"),
+                    I18N.getString("param.preferences-id.description"),
+                    "preferencesID",
+                    String.class,
+                    p -> Optional.ofNullable(IDENTIFIER.fetchFrom(p)).
+                             orElse("").replace('.', '/'),
+                    (s, p) -> s
+            );
+
+    // TODO: remove it?
+    public static final StandardBundlerParam<String> PRELOADER_CLASS =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.preloader.name"),
+                    I18N.getString("param.preloader.description"),
+                    "preloader",
+                    String.class,
+                    p -> null,
+                    null
+            );
+
+    public static final StandardBundlerParam<Boolean> VERBOSE  =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.verbose.name"),
+                    I18N.getString("param.verbose.description"),
+                    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)
+            );
+
+    public static final StandardBundlerParam<File> DROP_IN_RESOURCES_ROOT =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.drop-in-resources-root.name"),
+                    I18N.getString("param.drop-in-resources-root.description"),
+                    "dropinResourcesRoot",
+                    File.class,
+                    params -> new File("."),
+                    (s, p) -> new File(s)
+            );
+
+    public static final BundlerParamInfo<String> INSTALL_DIR =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.install-dir.name"),
+                    I18N.getString("param.install-dir.description"),
+                    Arguments.CLIOptions.INSTALL_DIR.getId(),
+                    String.class,
+                     params -> null,
+                    (s, p) -> s
+    );
+
+    public static final StandardBundlerParam<File> PREDEFINED_APP_IMAGE =
+            new StandardBundlerParam<>(
+            I18N.getString("param.predefined-app-image.name"),
+            I18N.getString("param.predefined-app-image.description"),
+            Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId(),
+            File.class,
+            params -> null,
+            (s, p) -> new File(s));
+
+    public static final StandardBundlerParam<File> PREDEFINED_RUNTIME_IMAGE =
+            new StandardBundlerParam<>(
+            I18N.getString("param.predefined-runtime-image.name"),
+            I18N.getString("param.predefined-runtime-image.description"),
+            Arguments.CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId(),
+            File.class,
+            params -> null,
+            (s, p) -> new File(s));
+
+    @SuppressWarnings("unchecked")
+    public static final StandardBundlerParam<List<Map<String, ? super Object>>> SECONDARY_LAUNCHERS =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.secondary-launchers.name"),
+                    I18N.getString("param.secondary-launchers.description"),
+                    Arguments.CLIOptions.SECONDARY_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")
+    public static final StandardBundlerParam
+            <List<Map<String, ? super Object>>> FILE_ASSOCIATIONS =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.file-associations.name"),
+                    I18N.getString("param.file-associations.description"),
+                    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")
+    public static final StandardBundlerParam<List<String>> FA_EXTENSIONS =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.fa-extension.name"),
+                    I18N.getString("param.fa-extension.description"),
+                    "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")
+    public static final StandardBundlerParam<List<String>> FA_CONTENT_TYPE =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.fa-content-type.name"),
+                    I18N.getString("param.fa-content-type.description"),
+                    "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)+"))
+            );
+
+    public static final StandardBundlerParam<String> FA_DESCRIPTION =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.fa-description.name"),
+                    I18N.getString("param.fa-description.description"),
+                    "fileAssociation.description",
+                    String.class,
+                    params -> APP_NAME.fetchFrom(params) + " File",
+                    null
+            );
+
+    public static final StandardBundlerParam<File> FA_ICON =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.fa-icon.name"),
+                    I18N.getString("param.fa-icon.description"),
+                    "fileAssociation.icon",
+                    File.class,
+                    ICON::fetchFrom,
+                    (s, p) -> new File(s)
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final BundlerParamInfo<List<Path>> MODULE_PATH =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.module-path.name"),
+                    I18N.getString("param.module-path.description"),
+                    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();
+                        }
+
+                        // 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)) {
+                            jdk.packager.internal.Log.info(
+                                String.format(I18N.getString(
+                                        "warning.no.jdk.modules.found")));
+                        }
+
+                        return modulePath;
+                    });
+
+    @SuppressWarnings("unchecked")
+    public static final BundlerParamInfo<String> MODULE =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.main.module.name"),
+                    I18N.getString("param.main.module.description"),
+                    Arguments.CLIOptions.MODULE.getId(),
+                    String.class,
+                    p -> null,
+                    (s, p) -> {
+                        return String.valueOf(s);
+                    });
+
+    @SuppressWarnings("unchecked")
+    public static final BundlerParamInfo<Set<String>> ADD_MODULES =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.add-modules.name"),
+                    I18N.getString("param.add-modules.description"),
+                    Arguments.CLIOptions.ADD_MODULES.getId(),
+                    (Class<Set<String>>) (Object) Set.class,
+                    p -> new LinkedHashSet(),
+                    (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(",")))
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final BundlerParamInfo<Set<String>> LIMIT_MODULES =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.limit-modules.name"),
+                    I18N.getString("param.limit-modules.description"),
+                    Arguments.CLIOptions.LIMIT_MODULES.getId(),
+                    (Class<Set<String>>) (Object) Set.class,
+                    p -> new LinkedHashSet(),
+                    (s, p) -> new LinkedHashSet<>(Arrays.asList(s.split(",")))
+            );
+
+    @SuppressWarnings("unchecked")
+    public static final BundlerParamInfo<Boolean> STRIP_NATIVE_COMMANDS =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.strip-executables.name"),
+                    I18N.getString("param.strip-executables.description"),
+                    Arguments.CLIOptions.STRIP_NATIVE_COMMANDS.getId(),
+                    Boolean.class,
+                    p -> Boolean.FALSE,
+                    (s, p) -> Boolean.valueOf(s)
+            );
+
+    public static final BundlerParamInfo<Boolean> SINGLETON =
+           new StandardBundlerParam<> (
+                    I18N.getString("param.singleton.name"),
+                    I18N.getString("param.singleton.description"),
+                    Arguments.CLIOptions.SINGLETON.getId(),
+                    Boolean.class,
+                    params -> Boolean.FALSE,
+                    (s, p) -> Boolean.valueOf(s)
+    );
+
+    public static final BundlerParamInfo<Boolean> ECHO_MODE =
+            new StandardBundlerParam<> (
+                    I18N.getString("param.echo-mode.name"),
+                    I18N.getString("param.echo-mode.description"),
+                    Arguments.CLIOptions.ECHO_MODE.getId(),
+                    Boolean.class,
+                    params -> Boolean.FALSE,
+                    (s, p) -> Boolean.valueOf(s)
+    );
+
+    public static File getPredefinedAppImage(Map<String, ? super Object> p) {
+        File applicationImage = null;
+        if (PREDEFINED_APP_IMAGE.fetchFrom(p) != null) {
+            applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(p);
+            Log.debug("Using App Image from " + applicationImage);
+            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;
+    }
+
+    public static void copyPredefinedRuntimeImage(
+            Map<String, ? super Object> p,
+            AbstractAppImageBuilder appBuilder)
+            throws IOException , ConfigException {
+        File image = PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
+        if (!image.exists()) {
+            throw new ConfigException(
+                    MessageFormat.format(I18N.getString(
+                    "message.runtime-image-dir-does-not-exist"),
+                    PREDEFINED_RUNTIME_IMAGE.getID(),
+                    image.toString()),
+                    MessageFormat.format(I18N.getString(
+                    "message.runtime-image-dir-does-not-exist.advice"),
+                    PREDEFINED_RUNTIME_IMAGE.getID()));
+        }
+        IOUtils.copyRecursive(image.toPath(), appBuilder.getRoot());
+        appBuilder.prepareApplicationFiles();
+    }
+
+    public 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());
+        boolean jreInstaller =
+                params.containsKey(Arguments.CREATE_JRE_INSTALLER.getID());
+
+        if (hasMainClass && hasMainJar && hasMainJarClassPath || hasModule ||
+                jreInstaller) {
+            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();
+            }
+        }
+    }
+
+    public 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 jreInstaller =
+                params.containsKey(Arguments.CREATE_JRE_INSTALLER.getID());
+
+        if (hasMainClass && hasMainJar && hasMainJarClassPath ||
+                hasModule || jreInstaller) {
+            return;
+        }
+
+        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 if (hasMainJarClassPath) {
+                throw new ConfigException(
+                        I18N.getString("error.no-main-class-with-classpath"),
+                        I18N.getString(
+                        "error.no-main-class-with-classpath.advice"));
+            } else {
+                throw new ConfigException(
+                        I18N.getString("error.no-main-class"),
+                        I18N.getString("error.no-main-class.advice"));
+            }
+        }
+    }
+
+
+    private static List<String> splitStringWithEscapes(String s) {
+        List<String> l = new ArrayList<>();
+        StringBuilder current = new StringBuilder();
+        boolean quoted = false;
+        boolean escaped = false;
+        for (char c : s.toCharArray()) {
+            if (escaped) {
+                current.append(c);
+            } else if ('"' == c) {
+                quoted = !quoted;
+            } else if (!quoted && Character.isWhitespace(c)) {
+                l.add(current.toString());
+                current = new StringBuilder();
+            } else {
+                current.append(c);
+            }
+        }
+        l.add(current.toString());
+        return l;
+    }
+
+    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 {
+                    Files.walk(f.toPath())
+                            .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 moduleName, Map<String, ? super Object> params) {
+        for (RelativeFileSet rfs : APP_RESOURCES_LIST.fetchFrom(params)) {
+            File appResourcesRoot = rfs.getBaseDirectory();
+            File mainJarFile = new File(appResourcesRoot, moduleName);
+
+            if (mainJarFile.exists()) {
+                return new RelativeFileSet(appResourcesRoot,
+                     new LinkedHashSet<>(Collections.singletonList(
+                     mainJarFile)));
+            }
+            else {
+                List<Path> modulePath = MODULE_PATH.fetchFrom(params);
+                Path modularJarPath = JLinkBundlerHelper.findPathOfModule(
+                        modulePath, moduleName);
+
+                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"),
+                        moduleName), I18N.getString(
+                        "error.main-jar-does-not-exist.advice")));
+    }
+
+    public static List<Path> getDefaultModulePath() {
+        List<Path> result = new ArrayList();
+        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;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/UnsupportedPlatformException.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal;
+
+
+public class UnsupportedPlatformException extends Exception {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/ValidOptions.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 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.packager.internal;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import jdk.packager.internal.Arguments.CLIOptions;
+
+
+public class ValidOptions {
+
+    private ValidOptions() {};
+
+    // multimap that contains pairs of (mode, supported args)
+    private static final Map<CLIOptions, Set<CLIOptions>> options =
+            new HashMap<>();
+
+    private static boolean argsInitialized = false;
+
+    // initializing list of mandatory arguments
+    private static void initArgs() {
+        if (argsInitialized) {
+            return;
+        }
+
+        // add options for CREATE_IMAGE   
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.INPUT);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.OUTPUT); 
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.APPCLASS);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.SINGLETON);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.NAME);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.IDENTIFIER);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.VERBOSE);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.FILES);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.ARGUMENTS);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.STRIP_NATIVE_COMMANDS);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.ICON);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.VERSION);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.JVM_ARGS);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.USER_JVM_ARGS);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.USER_JVM_ARGS);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.SECONDARY_LAUNCHER);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.BUILD_ROOT);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.ECHO_MODE);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.PREDEFINED_RUNTIME_IMAGE);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.MAIN_JAR);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.MODULE);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.ADD_MODULES);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.MODULE_PATH);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.LIMIT_MODULES);
+
+        if (Platform.getPlatform() == Platform.MAC) {
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.MAC_SIGN);
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.MAC_BUNDLE_NAME);
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.MAC_BUNDLE_IDENTIFIER);
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.MAC_BUNDLE_SIGNING_PREFIX);
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.MAC_SIGNING_KEY_NAME);
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.MAC_SIGNING_KEYCHAIN);
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.CATEGORY);
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.COPYRIGHT);
+        }
+
+        if (Platform.getPlatform() == Platform.WINDOWS) {
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.DESCRIPTION);
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.VENDOR);
+            add(CLIOptions.CREATE_IMAGE, CLIOptions.COPYRIGHT);
+        }
+
+        // add options for CREATE_INSTALLER
+
+        // add all CREATE_IMAGE options for CREATE_JRE_INSTALLER
+        Set<CLIOptions> imageOptions = options.get(CLIOptions.CREATE_IMAGE);
+        imageOptions.forEach(o -> add(CLIOptions.CREATE_INSTALLER, o));
+
+        add(CLIOptions.CREATE_INSTALLER, CLIOptions.LICENSE_FILE);
+        add(CLIOptions.CREATE_INSTALLER, CLIOptions.FILE_ASSOCIATIONS);
+        add(CLIOptions.CREATE_INSTALLER, CLIOptions.INSTALL_DIR);
+        add(CLIOptions.CREATE_INSTALLER, CLIOptions.PREDEFINED_APP_IMAGE);
+
+        if (Platform.getPlatform() == Platform.MAC) {
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.MAC_APP_STORE_CATEGORY);
+            add(CLIOptions.CREATE_INSTALLER,
+                    CLIOptions.MAC_APP_STORE_ENTITLEMENTS);
+        }
+
+        if (Platform.getPlatform() == Platform.LINUX) {
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.LINUX_BUNDLE_NAME);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.LINUX_DEB_MAINTAINER);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.LINUX_RPM_LICENSE_TYPE);
+            add(CLIOptions.CREATE_INSTALLER,
+                    CLIOptions.LINUX_PACKAGE_DEPENDENCIES);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.DESCRIPTION);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.VENDOR);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.CATEGORY);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.COPYRIGHT);
+        }
+
+        if (Platform.getPlatform() == Platform.WINDOWS) {
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.WIN_MENU_HINT);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.WIN_MENU_GROUP);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.WIN_SHORTCUT_HINT);
+            add(CLIOptions.CREATE_INSTALLER,
+                    CLIOptions.WIN_PER_USER_INSTALLATION);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.WIN_DIR_CHOOSER);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.WIN_REGISTRY_NAME);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.WIN_MSI_UPGRADE_UUID);
+            add(CLIOptions.CREATE_INSTALLER, CLIOptions.CATEGORY);
+        }
+
+        // add options for CREATE_JRE_INSTALLER
+        
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.INPUT);
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.OUTPUT); 
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.NAME);
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.VERBOSE);        
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.FILES);
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.STRIP_NATIVE_COMMANDS);
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.LICENSE_FILE);
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.VERSION);
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.BUILD_ROOT);
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.INSTALL_DIR);
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.ECHO_MODE);
+        add(CLIOptions.CREATE_JRE_INSTALLER,
+                    CLIOptions.PREDEFINED_RUNTIME_IMAGE);
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.ADD_MODULES); 
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.MODULE_PATH); 
+        add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.LIMIT_MODULES);
+
+        if (Platform.getPlatform() == Platform.MAC) {
+            add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.MAC_SIGN);
+            add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.MAC_BUNDLE_NAME);
+            add(CLIOptions.CREATE_JRE_INSTALLER,
+                    CLIOptions.MAC_BUNDLE_IDENTIFIER);
+            add(CLIOptions.CREATE_JRE_INSTALLER,
+                    CLIOptions.MAC_BUNDLE_SIGNING_PREFIX);
+            add(CLIOptions.CREATE_JRE_INSTALLER,
+                    CLIOptions.MAC_SIGNING_KEY_NAME);
+            add(CLIOptions.CREATE_JRE_INSTALLER,
+                    CLIOptions.MAC_SIGNING_KEYCHAIN);
+        }
+
+        if (Platform.getPlatform() == Platform.WINDOWS) {
+            add(CLIOptions.CREATE_JRE_INSTALLER,
+                    CLIOptions.WIN_PER_USER_INSTALLATION);
+            add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.WIN_DIR_CHOOSER);
+            add(CLIOptions.CREATE_JRE_INSTALLER,
+                    CLIOptions.WIN_MSI_UPGRADE_UUID);
+            add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.DESCRIPTION);
+            add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.VENDOR);
+        }        
+
+        if (Platform.getPlatform() == Platform.LINUX) {
+            add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.LINUX_BUNDLE_NAME);
+            add(CLIOptions.CREATE_JRE_INSTALLER,
+                    CLIOptions.LINUX_DEB_MAINTAINER); 
+            add(CLIOptions.CREATE_JRE_INSTALLER,
+                    CLIOptions.LINUX_PACKAGE_DEPENDENCIES);
+            add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.DESCRIPTION);
+            add(CLIOptions.CREATE_JRE_INSTALLER, CLIOptions.VENDOR);
+            add(CLIOptions.CREATE_JRE_INSTALLER,
+                    CLIOptions.LINUX_RPM_LICENSE_TYPE);
+        }
+
+        argsInitialized = true;
+    }
+
+    public static void add(CLIOptions mode, CLIOptions arg) {
+        if (mode.equals(arg)) {
+            return;
+        }
+        options.computeIfAbsent(mode,
+                    k -> new HashSet<>()).add(arg);
+    }
+
+    public static boolean checkIfSupported(CLIOptions mode, CLIOptions arg) {
+        if (mode.equals(arg)) {
+            return true;
+        }
+
+        initArgs();
+        Set<CLIOptions> set = options.get(mode);
+        if (set != null) {
+            return set.contains(arg);
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/builders/AbstractAppImageBuilder.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2015, 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.packager.internal.builders;
+
+
+import jdk.packager.internal.IOUtils;
+
+import jdk.packager.internal.Log;
+import jdk.packager.internal.StandardBundlerParam;
+
+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 static jdk.packager.internal.StandardBundlerParam.*;
+import static jdk.packager.internal.StandardBundlerParam.ARGUMENTS;
+import static jdk.packager.internal.StandardBundlerParam.USER_JVM_OPTIONS;
+import java.util.ArrayList;
+import jdk.packager.internal.JLinkBundlerHelper;
+import jdk.packager.internal.Module;
+
+
+public abstract class AbstractAppImageBuilder {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle("jdk.packager.internal.resources.builders.AbstractAppImageBuilder");
+
+    //do not use file separator -
+    // we use it for classpath lookup and there / are not platform specific
+    public final static String BUNDLER_PREFIX = "package/";
+
+    private final Map<String, Object> properties;
+    private final Path root;
+    protected List<String> excludeFileList = new ArrayList<>();
+
+    public AbstractAppImageBuilder(Map<String, Object> properties, Path root) throws IOException {
+        this.properties = properties;
+        this.root = root;
+        excludeFileList.add(".*\\.diz");
+    }
+
+    public abstract InputStream getResourceAsStream(String name);
+    public abstract void prepareApplicationFiles() throws IOException;
+    public abstract void prepareServerJreFiles() throws IOException;
+
+    public Map<String, Object> getProperties() {
+        return this.properties;
+    }
+
+    public Path getRoot() {
+        return this.root;
+    }
+
+    public String getExcludeFileList() {
+        String result = "";
+
+        for (String item : excludeFileList) {
+            if (!result.isEmpty()) {
+                result += ",";
+            }
+
+            result += item;
+        }
+
+        return result;
+    }
+
+    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);
+        }
+    }
+
+    protected InputStream locateResource(String publicName, String category,
+                                         String defaultName, File customFile,
+                                         boolean verbose, File publicRoot) throws IOException {
+        InputStream is = null;
+        boolean customFromClasspath = false;
+        boolean customFromFile = false;
+        if (publicName != null) {
+            if (publicRoot != null) {
+                File publicResource = new File(publicRoot, publicName);
+                if (publicResource.exists() && publicResource.isFile()) {
+                    is = new FileInputStream(publicResource);
+                }
+            } else {
+                is = getResourceAsStream(publicName);
+            }
+            customFromClasspath = (is != null);
+        }
+        if (is == null && customFile != null) {
+            is = new FileInputStream(customFile);
+            customFromFile = (is != null);
+        }
+        if (is == null && defaultName != null) {
+            is = getResourceAsStream(defaultName);
+        }
+        String msg = null;
+        if (customFromClasspath) {
+            msg = MessageFormat.format(I18N.getString("message.using-custom-resource-from-classpath"), category == null ? "" : "[" + category + "] ", publicName);
+        } else if (customFromFile) {
+            msg = MessageFormat.format(I18N.getString("message.using-custom-resource-from-file"), category == null ? "" : "[" + category + "] ", customFile.getAbsoluteFile());
+        } else if (is != null) {
+            msg = MessageFormat.format(I18N.getString("message.using-default-resource-from-classpath"), category == null ? "" : "[" + category + "] ", publicName);
+        } else {
+            msg = MessageFormat.format(I18N.getString("message.using-default-resource"), category == null ? "" : "[" + category + "] ", publicName);
+        }
+        if (verbose) {
+            Log.info(msg);
+        }
+        return is;
+    }
+
+
+    protected String preprocessTextResource(String publicName, String category,
+                                            String defaultName, Map<String, String> pairs,
+                                            boolean verbose, File publicRoot) throws IOException {
+        InputStream inp = locateResource(publicName, category, defaultName, null, verbose, publicRoot);
+        if (inp == null) {
+            throw new RuntimeException("Module corrupt? No "+defaultName+" resource!");
+        }
+
+        try (InputStream is = inp) {
+            //read fully into memory
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int length;
+            while ((length = is.read(buffer)) != -1) {
+                baos.write(buffer, 0, length);
+            }
+
+            //substitute
+            String result = new String(baos.toByteArray());
+            for (Map.Entry<String, String> e : pairs.entrySet()) {
+                if (e.getValue() != null) {
+                    result = result.replace(e.getKey(), e.getValue());
+                }
+            }
+            return result;
+        }
+    }
+
+    public void writeCfgFile(Map<String, ? super Object> params, File cfgFileName, String runtimeLocation) throws IOException {
+        cfgFileName.delete();
+
+        File mainJar = JLinkBundlerHelper.getMainJar(params);
+        Module.ModuleType mainJarType = Module.ModuleType.Unknown;
+
+        if (mainJar != null) {
+            mainJarType = new Module(mainJar).getModuleType();
+        }
+
+        String mainModule = StandardBundlerParam.MODULE.fetchFrom(params);
+
+        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.preferences.id=" + PREFERENCES_ID.fetchFrom(params));
+        out.println("app.runtime=" + runtimeLocation);
+        out.println("app.identifier=" + IDENTIFIER.fetchFrom(params));
+        out.println("app.classpath=" + String.join(File.pathSeparator, CLASSPATH.fetchFrom(params).split("[ :;]")));
+        out.println("app.application.instance=" + (SINGLETON.fetchFrom(params) ? "single" : "multiple"));
+
+        // The main app is required to be a jar, modular or unnamed.
+        if (mainModule != null && 
+                (mainJarType == Module.ModuleType.Unknown ||
+                mainJarType == Module.ModuleType.ModularJar)) {
+            out.println("app.mainmodule=" + mainModule);
+        } else {
+            String mainClass = JLinkBundlerHelper.getMainClass(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=" + mainJar.toPath().getFileName().toString());
+            }
+            if (mainClass != null) {
+                out.println("app.mainclass=" + mainClass.replaceAll("\\.", "/"));
+            }
+        }
+
+        String version = JLinkBundlerHelper.getJDKVersion(params);
+
+        if (!version.isEmpty()) {
+            out.println("app.java.version=" + version);
+        }
+
+        out.println("packager.java.version=" + System.getProperty("java.version"));
+
+        Integer port = JLinkBundlerHelper.DEBUG.fetchFrom(params);
+
+        if (port != null) {
+            out.println("app.debug=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:" + port);
+        }
+
+        out.println();
+        out.println("[JVMOptions]");
+        List<String> jvmargs = JVM_OPTIONS.fetchFrom(params);
+        for (String arg : jvmargs) {
+            out.println(arg);
+        }
+        Map<String, String> jvmProps = JVM_PROPERTIES.fetchFrom(params);
+        for (Map.Entry<String, String> property : jvmProps.entrySet()) {
+            out.println("-D" + property.getKey() + "=" + property.getValue());
+        }
+        String preloader = PRELOADER_CLASS.fetchFrom(params);
+        if (preloader != null) {
+            out.println("-Djavafx.preloader="+preloader);
+        }
+
+
+        out.println();
+        out.println("[JVMUserOptions]");
+        Map<String, String> overridableJVMOptions = USER_JVM_OPTIONS.fetchFrom(params);
+        for (Map.Entry<String, String> arg: overridableJVMOptions.entrySet()) {
+            if (arg.getKey() == null || arg.getValue() == null) {
+                Log.info(I18N.getString("message.jvm-user-arg-is-null"));
+            } else {
+                out.println(arg.getKey().replaceAll("([\\=])", "\\\\$1") + "=" + arg.getValue());
+            }
+        }
+
+        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);
+            }
+        }
+
+
+        out.close();
+    }
+
+    public String getPlatformSpecificModulesFile() {
+        return null;
+    }
+
+    protected abstract String getCacheLocation(Map<String, ? super Object> params);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/bundlers/BundleParams.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.bundlers;
+
+import jdk.packager.internal.*;
+import jdk.packager.internal.bundlers.Bundler.BundleType;
+
+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.packager.internal.StandardBundlerParam.*;
+
+import jdk.packager.internal.JLinkBundlerHelper;
+
+
+public class BundleParams {
+
+    final protected Map<String, ? super Object> params;
+
+    public static final String PARAM_RUNTIME                = "runtime"; // RelativeFileSet
+    public static final String PARAM_APP_RESOURCES          = "appResources"; // RelativeFileSet
+    public static final String PARAM_TYPE                   = "type"; // BundlerType
+    public static final String PARAM_BUNDLE_FORMAT          = "bundleFormat"; // String
+    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
+
+    /* 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"; // String
+
+    /* shortcut preferences */
+    public static final String PARAM_SHORTCUT               = "shortcutHint"; // boolean
+    public static final String PARAM_MENU                   = "menuHint"; // boolean
+
+    /* Application version. Format may differ for different bundlers */
+    public static final String PARAM_VERSION                = "appVersion"; // String
+    /* Application category. Used at least on Mac/Linux. Value is platform specific */
+    public static final String PARAM_CATEGORY               = "applicationCategory"; // String
+
+    /* Optional short application */
+    public static final String PARAM_TITLE                  = "title"; // 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(s) with license. Format is OS/bundler specific */
+    public static final String PARAM_LICENSE_FILE          = "licenseFile"; // List<String>
+
+    /* service/daemon install.
+       null means "default" */
+    public static final String PARAM_SERVICE_HINT           = "serviceHint"; // Boolean
+
+
+    /* Main application class. Not used directly but used to derive default values */
+    public static final String PARAM_APPLICATION_CLASS      = "applicationClass"; // String
+
+    /* Adds a dialog to let the user choose a directory where the product will be installed. */
+    public static final String PARAM_INSTALLDIR_CHOOSER     = "installdirChooser"; // Boolean
+
+    /* Prevents from launching multiple instances of application.  */
+    public static final String PARAM_SINGLETON              = "singleton"; // Boolean
+
+    /**
+     * 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> p) {
+        params.putAll(p);
+    }
+
+    public <C> C fetchParam(BundlerParamInfo<C> paramInfo) {
+        return paramInfo.fetchFrom(params);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <C> C fetchParamWithDefault(Class<C> klass, C defaultValue, String... keys) {
+        for (String key : keys) {
+            Object o = params.get(key);
+            if (klass.isInstance(o)) {
+                return (C) o;
+            }
+            else if (params.containsKey(keys) && o == null) {
+                return null;
+            }
+            //else if (o != null) {
+            //TODO log an error.
+            //}
+        }
+        return defaultValue;
+    }
+
+    public <C> C fetchParam(Class<C> klass, String... keys) {
+        return fetchParamWithDefault(klass, null, keys);
+    }
+
+    //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 void setJvmargs(List<String> jvmargs) {
+        putUnlessNullOrEmpty(JVM_OPTIONS.getID(), jvmargs);
+    }
+
+    public void setJvmUserArgs(Map<String, String> userArgs) {
+
+        putUnlessNullOrEmpty(USER_JVM_OPTIONS.getID(), userArgs);
+    }
+
+    public void setJvmProperties(Map<String, String> jvmProperties) {
+        putUnlessNullOrEmpty(JVM_PROPERTIES.getID(), jvmProperties);
+    }
+
+    public void setArguments(List<String> arguments) {
+        putUnlessNullOrEmpty(ARGUMENTS.getID(), arguments);
+    }
+
+    public void setAddModules(String value) {
+        putUnlessNull(StandardBundlerParam.ADD_MODULES.getID(), value);
+    }
+
+    public void setLimitModules(String value)  {
+        putUnlessNull(StandardBundlerParam.LIMIT_MODULES.getID(), value);
+    }
+
+    public void setStripNativeCommands(boolean value) {
+        putUnlessNull(StandardBundlerParam.STRIP_NATIVE_COMMANDS.getID(), value);
+    }
+
+    public void setDetectMods(boolean value) {
+        putUnlessNull(JLinkBundlerHelper.DETECT_MODULES.getID(), value);
+    }
+
+    public void setSrcDir(String value) {
+        putUnlessNull(SOURCE_DIR.getID(), value);
+    }
+
+    public void setModulePath(String value) {
+        putUnlessNull(StandardBundlerParam.MODULE_PATH.getID(), value);
+    }
+
+    public void setMainModule(String value) {
+        putUnlessNull(StandardBundlerParam.MODULE.getID(), value);
+    }
+
+    public void setDebug(String value) {
+        putUnlessNull(JLinkBundlerHelper.DEBUG.getID(), value);
+    }
+
+    public String getApplicationID() {
+        return fetchParam(IDENTIFIER);
+    }
+
+    public String getPreferencesID() {
+        return fetchParam(PREFERENCES_ID);
+    }
+
+    public String getTitle() {
+        return fetchParam(TITLE);
+    }
+
+    public void setTitle(String title) {
+        putUnlessNull(PARAM_TITLE, title);
+    }
+
+    public String getApplicationClass() {
+        return fetchParam(MAIN_CLASS);
+    }
+
+    public void setApplicationClass(String applicationClass) {
+        putUnlessNull(PARAM_APPLICATION_CLASS, applicationClass);
+    }
+
+    public void setPrelaoderClass(String preloaderClass) {
+        putUnlessNull(PRELOADER_CLASS.getID(), preloaderClass);
+    }
+
+    public String getAppVersion() {
+        return fetchParam(VERSION);
+    }
+
+    public void setAppVersion(String version) {
+        putUnlessNull(PARAM_VERSION, version);
+    }
+
+    public String getDescription() {
+        return fetchParam(DESCRIPTION);
+    }
+
+    public void setDescription(String s) {
+        putUnlessNull(PARAM_DESCRIPTION, s);
+    }
+
+    //path is relative to the application root
+    public void addLicenseFile(String path) {
+        List<String> licenseFiles = fetchParam(LICENSE_FILE);
+        if (licenseFiles == null || licenseFiles.isEmpty()) {
+            licenseFiles = new ArrayList<>();
+            params.put(PARAM_LICENSE_FILE, licenseFiles);
+        }
+        licenseFiles.add(path);
+    }
+
+    public void setServiceHint(Boolean b) {
+        putUnlessNull(PARAM_SERVICE_HINT, b);
+    }
+
+    public void setInstalldirChooser(Boolean b) {
+        putUnlessNull(PARAM_INSTALLDIR_CHOOSER, b);
+    }
+
+    public void setSingleton(Boolean b) {
+        putUnlessNull(PARAM_SINGLETON, b);
+    }
+
+    public String getName() {
+        return fetchParam(APP_NAME);
+    }
+
+    public void setName(String name) {
+        putUnlessNull(PARAM_NAME, name);
+    }
+
+    @SuppressWarnings("deprecation")
+    public BundleType getType() {
+        return fetchParam(BundleType.class, PARAM_TYPE);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void setType(BundleType type) {
+        putUnlessNull(PARAM_TYPE, type);
+    }
+
+    public String getBundleFormat() {
+        return fetchParam(String.class, PARAM_BUNDLE_FORMAT);
+    }
+
+    public void setBundleFormat(String t) {
+        putUnlessNull(PARAM_BUNDLE_FORMAT, t);
+    }
+
+    public boolean getVerbose() {
+        return fetchParam(VERBOSE);
+    }
+
+    public void setVerbose(Boolean verbose) {
+        putUnlessNull(VERBOSE.getID(), verbose);
+    }
+
+    public List<String> getLicenseFile() {
+        return fetchParam(LICENSE_FILE);
+    }
+
+    public List<String> getJvmargs() {
+        return JVM_OPTIONS.fetchFrom(params);
+    }
+
+    public List<String> getArguments() {
+        return ARGUMENTS.fetchFrom(params);
+    }
+
+    // Validation approach:
+    //  - javac and
+    //
+    //  - /jmods dir
+    // or
+    //  - JRE marker (rt.jar)
+    //  - FX marker (jfxrt.jar)
+    //  - JDK marker (tools.jar)
+    private static boolean checkJDKRoot(File jdkRoot) {
+        String exe = (Platform.getPlatform() == Platform.WINDOWS) ? ".exe" : "";
+        File javac = new File(jdkRoot, "bin/javac" + exe);
+        if (!javac.exists()) {
+            Log.verbose("javac is not found at " + javac.getAbsolutePath());
+            return false;
+        }
+
+        File jmods = new File(jdkRoot, "jmods");
+        if (!jmods.exists()) {
+            // old non-modular JDKs
+            File rtJar = new File(jdkRoot, "jre/lib/rt.jar");
+            if (!rtJar.exists()) {
+                Log.verbose("rt.jar is not found at " + rtJar.getAbsolutePath());
+                return false;
+            }
+
+            File jfxJar = new File(jdkRoot, "jre/lib/ext/jfxrt.jar");
+            if (!jfxJar.exists()) {
+                //Try again with new location
+                jfxJar = new File(jdkRoot, "jre/lib/jfxrt.jar");
+                if (!jfxJar.exists()) {
+                    Log.verbose("jfxrt.jar is not found at " + jfxJar.getAbsolutePath());
+                    return false;
+                }
+            }
+
+
+            File toolsJar = new File(jdkRoot, "lib/tools.jar");
+            if (!toolsJar.exists()) {
+                Log.verbose("tools.jar is not found at " + toolsJar.getAbsolutePath());
+                return false;
+            }
+        }
+        return true;
+    }
+
+    //Depending on platform and user input we may get different "references"
+    //Should support
+    //   - java.home
+    //   - reference to JDK install folder
+    //   - should NOT support JRE dir
+    //Note: input could be null (then we asked to use system JRE)
+    //       or it must be valid directory
+    //Returns null on validation failure. Returns jre root if ok.
+    public static File validateRuntimeLocation(File javaHome) {
+        if (javaHome == null) {
+            return null;
+        }
+
+        File jdkRoot;
+        File rtJar = new File(javaHome, "lib/rt.jar");
+
+        if (rtJar.exists()) { //must be "java.home" case
+                              //i.e. we are in JRE folder
+            jdkRoot = javaHome.getParentFile();
+        } else { //expect it to be root of JDK installation folder
+            //On Mac it could be jdk/ or jdk/Contents/Home
+            //Norm to jdk/Contents/Home for validation
+            if (Platform.getPlatform() == Platform.MAC) {
+                File f = new File(javaHome, "Contents/Home");
+                if (f.exists() && f.isDirectory()) {
+                    javaHome = f;
+                }
+            }
+            jdkRoot = javaHome;
+        }
+
+        if (!checkJDKRoot(jdkRoot)) {
+            throw new RuntimeException(
+                    "Can not find JDK artifacts in specified location: "
+                    + javaHome.getAbsolutePath());
+        }
+
+        return new File(jdkRoot, "jre");
+    }
+
+    //select subset of given runtime using predefined rules
+    public void setRuntime(File baseDir) {
+        baseDir = validateRuntimeLocation(baseDir);
+
+        //mistake or explicit intent to use system runtime
+        if (baseDir == null) {
+            Log.verbose("No Java runtime to embed. Package will need system Java.");
+            params.put(PARAM_RUNTIME, null);
+            return;
+        }
+        doSetRuntime(baseDir);
+    }
+
+    //input dir "jdk/jre" (i.e. jre folder in the jdk)
+    private void doSetRuntime(File baseDir) {
+        params.put(PARAM_RUNTIME, baseDir.toString());
+    }
+
+    //Currently unused?
+    //
+    //public void setRuntime(RelativeFileSet fs) {
+    //       runtime = fs;
+    //}
+
+    public jdk.packager.internal.RelativeFileSet getAppResource() {
+        return fetchParam(APP_RESOURCES);
+    }
+
+    public void setAppResource(jdk.packager.internal.RelativeFileSet fs) {
+        putUnlessNull(PARAM_APP_RESOURCES, fs);
+    }
+
+    public void setAppResourcesList(List<jdk.packager.internal.RelativeFileSet> rfs) {
+        putUnlessNull(APP_RESOURCES_LIST.getID(), rfs);
+    }
+
+    public File getIcon() {
+        return fetchParam(ICON);
+    }
+
+    public void setIcon(File icon) {
+        putUnlessNull(PARAM_ICON, icon);
+    }
+
+    public String getApplicationCategory() {
+        return fetchParam(CATEGORY);
+    }
+
+    public void setApplicationCategory(String category) {
+        putUnlessNull(PARAM_CATEGORY, category);
+    }
+
+    public String getMainClassName() {
+        String applicationClass = getApplicationClass();
+
+        if (applicationClass == null) {
+            return null;
+        }
+
+        int idx = applicationClass.lastIndexOf(".");
+        if (idx >= 0) {
+            return applicationClass.substring(idx+1);
+        }
+        return applicationClass;
+    }
+
+    public String getCopyright() {
+        return fetchParam(COPYRIGHT);
+    }
+
+    public void setCopyright(String c) {
+        putUnlessNull(PARAM_COPYRIGHT, c);
+    }
+
+    public String getIdentifier() {
+        return fetchParam(IDENTIFIER);
+    }
+
+    public void setIdentifier(String s) {
+        putUnlessNull(PARAM_IDENTIFIER, s);
+    }
+
+    private String mainJar = null;
+    private String mainJarClassPath = null;
+    private boolean useFXPackaging = true;
+
+    //For regular executable Jars we need to take care of classpath
+    //For JavaFX executable jars we do not need to pay attention to ClassPath entry in manifest
+    public String getAppClassPath() {
+        if (mainJar == null) {
+            //this will find out answer
+            getMainApplicationJar();
+        }
+        if (useFXPackaging || mainJarClassPath == null) {
+            return "";
+        }
+        return mainJarClassPath;
+    }
+
+    //assuming that application was packaged according to the rules
+    // we must have application jar, i.e. jar where we embed launcher
+    // and have main application class listed as main class!
+    //If there are more than one, or none - it will be treated as deployment error
+    //
+    //Note we look for both JavaFX executable jars and regular executable jars
+    //As long as main "application" entry point is the same it is main class
+    // (i.e. for FX jar we will use JavaFX manifest entry ...)
+    public String getMainApplicationJar() {
+        if (mainJar != null) {
+            return mainJar;
+        }
+
+        jdk.packager.internal.RelativeFileSet appResources = getAppResource();
+        String applicationClass = getApplicationClass();
+
+        if (appResources == null || applicationClass == null) {
+            return null;
+        }
+        File srcdir = appResources.getBaseDirectory();
+        for (String fname : appResources.getIncludedFiles()) {
+            JarFile jf;
+            try {
+                jf = new JarFile(new File(srcdir, fname));
+                Manifest m = jf.getManifest();
+                Attributes attrs = (m != null) ? m.getMainAttributes() : null;
+                if (attrs != null) {
+                    boolean javaMain = applicationClass.equals(
+                               attrs.getValue(Attributes.Name.MAIN_CLASS));
+
+                    if (javaMain) {
+                        mainJar = fname;
+                        mainJarClassPath = attrs.getValue(Attributes.Name.CLASS_PATH);
+                        return mainJar;
+                    }
+                }
+            } catch (IOException ignore) {
+            }
+        }
+        return null;
+    }
+
+    public String getVendor() {
+        return fetchParam(VENDOR);
+    }
+
+    public void setVendor(String vendor) {
+       putUnlessNull(PARAM_VENDOR, vendor);
+    }
+
+    public String getEmail() {
+        return fetchParam(String.class, PARAM_EMAIL);
+    }
+
+    public void setEmail(String email) {
+        putUnlessNull(PARAM_EMAIL, email);
+    }
+
+    public void putUnlessNull(String param, Object value) {
+        if (value != null) {
+            params.put(param, value);
+        }
+    }
+
+    public void putUnlessNullOrEmpty(String param, Collection value) {
+        if (value != null && !value.isEmpty()) {
+            params.put(param, value);
+        }
+    }
+
+    public void putUnlessNullOrEmpty(String param, Map value) {
+        if (value != null && !value.isEmpty()) {
+            params.put(param, value);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/bundlers/Bundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.bundlers;
+
+
+public final class Bundler {
+
+    private Bundler() {}
+
+    /**
+     * Located here for backwards compatibility
+     */
+    public enum BundleType {
+        NONE,
+        @Deprecated
+        ALL,      // Generates all bundlers
+        NATIVE,   // Generates both app image and all installers
+        IMAGE,    // Generates app image only
+        INSTALLER // Generates installers
+    }
+
+    @Deprecated
+    public static final class Bundle {
+        public BundleType type = BundleType.NONE;
+        public String format = null;
+    }
+
+    @Deprecated
+    static public Bundle stringToBundle(String value) {
+        Bundle result = new Bundle();
+
+        if (!value.isEmpty()) {
+            if ("false".equals(value) || "none".equals(value)) {
+                result.type = BundleType.NONE;
+            } else if ("all".equals(value) || "true".equals(value)) {
+                result.type = BundleType.ALL;
+            } else if ("image".equals(value)) {
+                result.type = BundleType.IMAGE;
+            } else if ("native".equals(value)) {
+                result.type = BundleType.NATIVE;
+            } else if ("installer".equals(value)) {
+                result.type = BundleType.INSTALLER;
+            } else {
+                //assume it is request to build only specific format (like exe or msi)
+                result.type = BundleType.INSTALLER;
+                result.format = (value != null) ? value.toLowerCase() : null;
+            }
+        }
+
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/AbstractBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,7 @@
+param.images-root.name=
+param.images-root.description=
+
+message.using-default-resource=Using default package resource {0} (add {1} to the class path to customize)
+message.using-custom-resource-from-file=Using custom package resource {0} (loaded from file {1})
+message.using-custom-resource-from-classpath=Using custom package resource {0} (loaded from {1})
+message.using-default-resource-from-classpath=Using default package resource {0} (add {1} to the class path to customize)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/AbstractBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,7 @@
+param.images-root.name=
+param.images-root.description=
+
+message.using-default-resource=\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528({1}\u3092\u30AF\u30E9\u30B9\u30FB\u30D1\u30B9\u306B\u8FFD\u52A0\u3057\u3066\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA)
+message.using-custom-resource-from-file=\u30AB\u30B9\u30BF\u30E0\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528(\u30D5\u30A1\u30A4\u30EB{1}\u304B\u3089\u30ED\u30FC\u30C9\u6E08)
+message.using-custom-resource-from-classpath=\u30AB\u30B9\u30BF\u30E0\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528({1}\u304B\u3089\u30ED\u30FC\u30C9\u6E08)
+message.using-default-resource-from-classpath=\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528({1}\u3092\u30AF\u30E9\u30B9\u30FB\u30D1\u30B9\u306B\u8FFD\u52A0\u3057\u3066\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/AbstractBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,7 @@
+param.images-root.name=
+param.images-root.description=
+
+message.using-default-resource=\u4F7F\u7528\u9ED8\u8BA4\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u5C06 {1} \u6DFB\u52A0\u5230\u7C7B\u8DEF\u5F84\u4EE5\u5B9A\u5236)
+message.using-custom-resource-from-file=\u4F7F\u7528\u5B9A\u5236\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u4ECE\u6587\u4EF6 {1} \u52A0\u8F7D)
+message.using-custom-resource-from-classpath=\u4F7F\u7528\u5B9A\u5236\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u4ECE {1} \u52A0\u8F7D)
+message.using-default-resource-from-classpath=\u4F7F\u7528\u9ED8\u8BA4\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u5C06 {1} \u6DFB\u52A0\u5230\u7C7B\u8DEF\u5F84\u4EE5\u5B9A\u5236)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/AbstractImageBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,25 @@
+param.launcher-cfg-format.name=Launcher .cfg File Format
+param.launcher-cfg-format.description=The file format of the .cfg file used by the launcher executable.  Current values are 'ini' and 'prop'.
+
+error.jre-missing-file=Java Runtime does not include {0}
+error.jre-missing-file.advice=Make sure ant is using Oracle JDK 8 or later.
+
+error.empty-user-jvm-option-value=UserJvmOption key ''{0}'' has a null or empty value.
+error.empty-user-jvm-option-value.advice=Provide a value for the key or split the key into a key/value pair.  Such as '-Xmx1G' into '-Xmx' and '1G'.
+
+error.no-application-class=Main application class is missing.
+error.no-application-class.advice=Please specify main application class.
+
+error.no-main-module=Main application module is missing.
+error.no-main-module.advice=Make sure to use fx\:module task to create modular application.
+
+error.app-cds-bad-version=AppCDS Not Supported in Bundled Runtime.
+error.app-cds-bad-version.advice=AppCDS support was added in 8u40.  Use an 8u40 or later Java Runtime
+
+error.app-cds-requires-runtime=AppCDS Not Supported with System Runtime.
+error.app-cds-requires-runtime.advice=AppCDS support requires that a runtime be bundled with the applicaiton.  The use of a System JRE is not supported.
+
+error.app-cds-no-commercial-unlock=AppCDS Requires Commercial Features to be Unlocked.
+error.app-cds-no-commercial-unlock.advice=Verify you have a license for commercial features for the Oracle Java Runtime the set the bundler argument 'commercialFeatures' to 'true'.
+
+message.jvm-user-arg-is-null=WARNING\: a jvmuserarg has a null name or value.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/AbstractImageBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,23 @@
+param.launcher-cfg-format.name=\u30e9\u30f3\u30c1\u30e3.cfg\u30d5\u30a1\u30a4\u30eb\u5f62\u5f0f
+param.launcher-cfg-format.description=\u30e9\u30f3\u30c1\u30e3\u5b9f\u884c\u53ef\u80fd\u30d5\u30a1\u30a4\u30eb\u306b\u3088\u308a\u4f7f\u7528\u3055\u308c\u308b.cfg\u30d5\u30a1\u30a4\u30eb\u306e\u30d5\u30a1\u30a4\u30eb\u5f62\u5f0f\u3002\u73fe\u5728\u306e\u5024\u306f'ini'\u304a\u3088\u3073'prop'\u3067\u3059\u3002
+
+error.jre-missing-file=Java\u30e9\u30f3\u30bf\u30a4\u30e0\u306b{0}\u306f\u542b\u307e\u308c\u3066\u3044\u307e\u305b\u3093
+error.jre-missing-file.advice=ant\u304cOracle JDK 8\u4ee5\u4e0a\u3092\u4f7f\u7528\u3057\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+
+error.empty-user-jvm-option-value=UserJvmOption\u30ad\u30fc''{0}''\u306bnull\u307e\u305f\u306f\u7a7a\u306e\u5024\u304c\u3042\u308a\u307e\u3059\u3002
+error.empty-user-jvm-option-value.advice=\u30ad\u30fc\u306e\u5024\u3092\u6307\u5b9a\u3059\u308b\u304b\u3001\u30ad\u30fc\u3092\u30ad\u30fc/\u5024\u306e\u30da\u30a2\u306b\u5206\u5272\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u305f\u3068\u3048\u3070\u3001'-Xmx1G'\u3092'-Xmx'\u3068'1G'\u306b\u5206\u5272\u3057\u307e\u3059\u3002
+
+
+error.no-main-module=\u30e1\u30a4\u30f3\u30fb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30fb\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u3042\u308a\u307e\u305b\u3093\u3002
+error.no-main-module.advice=fx:module\u30bf\u30b9\u30af\u3092\u4f7f\u7528\u3057\u3066\u3001\u30e2\u30b8\u30e5\u30e9\u30fb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u4f5c\u6210\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+
+error.app-cds-bad-version=AppCDS\u306f\u30d0\u30f3\u30c9\u30eb\u3055\u308c\u3066\u3044\u308b\u30e9\u30f3\u30bf\u30a4\u30e0\u3067\u306f\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002
+error.app-cds-bad-version.advice=AppCDS\u306e\u30b5\u30dd\u30fc\u30c8\u306f8u40\u3067\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\u30028u40\u4ee5\u4e0a\u306eJava\u30e9\u30f3\u30bf\u30a4\u30e0\u3092\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044
+
+error.app-cds-requires-runtime=AppCDS\u306f\u30b7\u30b9\u30c6\u30e0\u30fb\u30e9\u30f3\u30bf\u30a4\u30e0\u3067\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002
+error.app-cds-requires-runtime.advice=AppCDS\u306e\u30b5\u30dd\u30fc\u30c8\u306b\u306f\u3001\u30e9\u30f3\u30bf\u30a4\u30e0\u304c\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306b\u30d0\u30f3\u30c9\u30eb\u3055\u308c\u3066\u3044\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u30b7\u30b9\u30c6\u30e0JRE\u306e\u4f7f\u7528\u306f\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002
+
+error.app-cds-no-commercial-unlock=AppCDS\u306b\u306f\u3001\u5546\u7528\u6a5f\u80fd\u306e\u30ed\u30c3\u30af\u89e3\u9664\u304c\u5fc5\u8981\u3067\u3059\u3002
+error.app-cds-no-commercial-unlock.advice=\u30d0\u30f3\u30c9\u30e9\u5f15\u6570'commercialFeatures'\u3092'true'\u306b\u8a2d\u5b9a\u3057\u305fOracle Java Runtime\u306e\u5546\u7528\u6a5f\u80fd\u306e\u30e9\u30a4\u30bb\u30f3\u30b9\u3092\u6301\u3063\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002
+
+message.jvm-user-arg-is-null=\u8b66\u544a: jvmuserarg\u306bnull\u306e\u540d\u524d\u307e\u305f\u306f\u5024\u304c\u3042\u308a\u307e\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/AbstractImageBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,23 @@
+param.launcher-cfg-format.name=\u542f\u52a8\u7a0b\u5e8f .cfg \u6587\u4ef6\u683c\u5f0f
+param.launcher-cfg-format.description=\u542f\u52a8\u7a0b\u5e8f\u53ef\u6267\u884c\u6587\u4ef6\u4f7f\u7528\u7684 .cfg \u6587\u4ef6\u7684\u6587\u4ef6\u683c\u5f0f\u3002\u5f53\u524d\u503c\u4e3a 'ini' \u548c 'prop'\u3002
+
+error.jre-missing-file=Java \u8fd0\u884c\u65f6\u4e0d\u5305\u62ec {0}
+error.jre-missing-file.advice=\u786e\u4fdd ant \u4f7f\u7528\u7684\u662f Oracle JDK 8 \u6216\u66f4\u9ad8\u7248\u672c\u3002
+
+error.empty-user-jvm-option-value=UserJvmOption \u952e ''{0}'' \u5177\u6709\u7a7a\u503c\u6216\u503c\u4e3a\u7a7a\u3002
+error.empty-user-jvm-option-value.advice=\u63d0\u4f9b\u952e\u7684\u503c\u6216\u8005\u5c06\u952e\u62c6\u5206\u4e3a\u952e/\u503c\u5bf9\u3002\u4f8b\u5982\u5c06 '-Xmx1G' \u62c6\u5206\u4e3a '-Xmx' \u548c '1G'\u3002
+
+
+error.no-main-module=\u7f3a\u5c11\u4e3b\u5e94\u7528\u7a0b\u5e8f\u6a21\u5757\u3002
+error.no-main-module.advice=\u786e\u4fdd\u4f7f\u7528 fx:module \u4efb\u52a1\u521b\u5efa\u6a21\u5757\u5316\u5e94\u7528\u7a0b\u5e8f\u3002
+
+error.app-cds-bad-version=\u6253\u5305\u7684\u8fd0\u884c\u65f6\u4e2d\u4e0d\u652f\u6301 AppCDS\u3002
+error.app-cds-bad-version.advice=8u40 \u4e2d\u65b0\u589e\u4e86 AppCDS \u652f\u6301\u3002\u8bf7\u4f7f\u7528 8u40 \u6216\u66f4\u9ad8\u7248\u672c\u7684 Java \u8fd0\u884c\u65f6
+
+error.app-cds-requires-runtime=\u7cfb\u7edf\u8fd0\u884c\u65f6\u4e2d\u4e0d\u652f\u6301 AppCDS\u3002
+error.app-cds-requires-runtime.advice=AppCDS \u652f\u6301\u9700\u8981\u5c06\u8fd0\u884c\u65f6\u968f\u5e94\u7528\u7a0b\u5e8f\u4e00\u8d77\u6253\u5305\u3002\u4e0d\u652f\u6301\u4f7f\u7528\u7cfb\u7edf JRE\u3002
+
+error.app-cds-no-commercial-unlock=AppCDS \u9700\u8981\u5f00\u542f\u5546\u4e1a\u529f\u80fd\u3002
+error.app-cds-no-commercial-unlock.advice=\u786e\u4fdd\u60a8\u5177\u6709 Oracle Java \u8fd0\u884c\u65f6\u7684\u5546\u4e1a\u529f\u80fd\u8bb8\u53ef\u8bc1, \u5e76\u4e14\u5c06\u6253\u5305\u7a0b\u5e8f\u53c2\u6570 'commercialFeatures' \u8bbe\u7f6e\u4e3a 'true'\u3002
+
+message.jvm-user-arg-is-null=\u8b66\u544a: jvmuserarg \u7684\u540d\u79f0\u6216\u503c\u4e3a\u7a7a\u503c\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/Arguments.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,50 @@
+ERR_UnknownArgument=Error: Unknown argument: {0}
+ERR_UnknownCommand=Error: Unknown command: {0}
+ERR_UnknownReason=Unknown reason
+ERR_MissingArgument=Error: Missing argument: {0}
+ERR_EmbedingLauncher=Error: Missing embedded resource [{0}]
+ERR_ContradictorySetting=Error: Ant script manifest argument ''{0}'' contradicts Ant script data type settings.
+ERR_CreatingDirFailed=Error: Failed to create directory {0}
+ERR_CreatingFileFailed=Error: Failed to create file {0}
+ERR_CreatingTempFileFailed=Error: Failed to create temporary file
+ERR_CreatingJarFailed=Error: Failed to create jar file {0}
+ERR_FileCopyFailed=Error: Failed copy file to directory {0}
+ERR_FileReadFailed=Error: Failed reading file {0}
+ERR_CantDeleteFile=Error: File {0} could not be deleted.
+ERR_MissingDirectory=Missing directory {0}
+ERR_InvalidDirectory=Invalid directory {0}
+ERR_EmptySourceDirectory=Empty source directory {0}
+ERR_MissingJavaHome=Error: Java home directory is not known.
+ERR_MissingJavaFxHome=Error: JavaFx home directory is not known.
+ERR_JavacFailed=Error: javac execution failed, exit code: {0}
+ERR_MakeAllJavacFailed=Error: compilation of java sources failed
+ERR_DeployFailed=Error: deploy failed
+ERR_InvalidStoreFile=Error: Invalid keystore file: {0}
+ERR_SignFailed=Error: Signing failed
+ERR_MissingAppResources=Error: No application jars found
+ERR_NoEmbeddedDT=Error: -includedt requires the java deployment toolkit, which is not included in this distribution
+
+param.create-image.name=Create Image
+param.create-image.description=Creates platform-specific application image.
+
+param.create-installer.name=Create Installer
+param.create-installer.description=Creates platform-specific installer for the application.
+
+param.create-jre-installer.name=Create JRE Installer
+param.create-jre-installer.description=Creates platform-specific JRE installer.
+
+MSG_UpdatingJar=Updating jar file\: {0}
+MSG_DeprecatedArg=Warning: {0} has been deprecated and will be removed in a future release.
+MSG_DeprecatedMode=Warning: Mode {0} has been deprecated and will be removed in a future release.
+MSG_NoJREPackaged=Package is configured to ship without a JRE.
+MSG_UserProvidedJRE=Using base JDK at\: {0}
+MSG_UseSystemJRE=No base JDK. Package will use system JRE.
+MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a bundle.
+MSG_BundlerPlatformException=Bundler {0} skipped because the bundler does not support bundling on this platform.
+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_JarNoSelfCopy=Skip jar copy to itself\: {0}
+MSG_EnterKeystorePassword=Enter Passphrase for keystore:
+MSG_EnterKeyPassword=Enter key password for %s:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/Bundle.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,40 @@
+MSG_Version=jpackager version
+ERR_UnknownArgument=Error: Unknown argument: {0}
+ERR_UnknownCommand=Error: Unknown command: {0}
+ERR_UnknownReason=Unknown reason
+ERR_MissingArgument=Error: Missing argument: {0}
+ERR_EmbedingLauncher=Error: Missing embedded resource [{0}]
+ERR_ContradictorySetting=Error: Ant script manifest argument ''{0}'' contradicts Ant script data type settings.
+ERR_CreatingDirFailed=Error: Failed to create directory {0}
+ERR_CreatingFileFailed=Error: Failed to create file {0}
+ERR_CreatingTempFileFailed=Error: Failed to create temporary file
+ERR_CreatingJarFailed=Error: Failed to create jar file {0}
+ERR_FileCopyFailed=Error: Failed copy file to directory {0}
+ERR_FileReadFailed=Error: Failed reading file {0}
+ERR_CantDeleteFile=Error: File {0} could not be deleted.
+ERR_MissingDirectory=Missing directory {0}
+ERR_InvalidDirectory=Invalid directory {0}
+ERR_EmptySourceDirectory=Empty source directory {0}
+ERR_MissingJavaHome=Error: Java home directory is not known.
+ERR_MissingJavaFxHome=Error: JavaFx home directory is not known.
+ERR_JavacFailed=Error: javac execution failed, exit code: {0}
+ERR_MakeAllJavacFailed=Error: compilation of java sources failed
+ERR_DeployFailed=Error: deploy failed
+ERR_InvalidStoreFile=Error: Invalid keystore file: {0}
+ERR_SignFailed=Error: Signing failed
+ERR_MissingAppResources=Error: No application jars found
+ERR_NoEmbeddedDT=Error: -includedt requires the java deployment toolkit, which is not included in this distribution
+
+MSG_UpdatingJar=Updating jar file\: {0}
+MSG_NoJREPackaged=Package is configured to ship without a JRE.
+MSG_UserProvidedJRE=Using base JDK at\: {0}
+MSG_UseSystemJRE=No base JDK. Package will use system JRE.
+MSG_BundlerFailed=Error: Bundler "{1}" ({0}) failed to produce a bundle.
+MSG_BundlerPlatformException=Bundler {0} skipped because the bundler does not support bundling on this platform.
+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_JarNoSelfCopy=Skip jar copy to itself\: {0}
+MSG_EnterKeystorePassword=Enter Passphrase for keystore:
+MSG_EnterKeyPassword=Enter key password for %s:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/Bundle_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,39 @@
+MSG_Version=Java\u30D1\u30C3\u30B1\u30FC\u30B8\u30E3\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3
+ERR_UnknownArgument=\u30A8\u30E9\u30FC: \u4E0D\u660E\u306A\u5F15\u6570: {0}
+ERR_UnknownCommand=\u30A8\u30E9\u30FC: \u4E0D\u660E\u306A\u30B3\u30DE\u30F3\u30C9: {0}
+ERR_UnknownReason=\u7406\u7531\u306F\u4E0D\u660E\u3067\u3059
+ERR_MissingArgument=\u30A8\u30E9\u30FC: \u5F15\u6570\u304C\u3042\u308A\u307E\u305B\u3093: {0}
+ERR_EmbedingLauncher=\u30A8\u30E9\u30FC: \u57CB\u8FBC\u307F\u30EA\u30BD\u30FC\u30B9[{0}]\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
+ERR_ContradictorySetting=\u30A8\u30E9\u30FC: Ant\u30B9\u30AF\u30EA\u30D7\u30C8\u30FB\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u5F15\u6570''{0}''\u306F\u3001Ant\u30B9\u30AF\u30EA\u30D7\u30C8\u30FB\u30C7\u30FC\u30BF\u578B\u8A2D\u5B9A\u3068\u77DB\u76FE\u3057\u3066\u3044\u307E\u3059\u3002
+ERR_CreatingDirFailed=\u30A8\u30E9\u30FC: \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+ERR_CreatingFileFailed=\u30A8\u30E9\u30FC: \u30D5\u30A1\u30A4\u30EB{0}\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+ERR_CreatingTempFileFailed=\u30A8\u30E9\u30FC: \u4E00\u6642\u30D5\u30A1\u30A4\u30EB\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+ERR_CreatingJarFailed=\u30A8\u30E9\u30FC: jar\u30D5\u30A1\u30A4\u30EB{0}\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+ERR_FileCopyFailed=\u30A8\u30E9\u30FC: \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3078\u306E\u30D5\u30A1\u30A4\u30EB\u306E\u30B3\u30D4\u30FC\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+ERR_FileReadFailed=\u30A8\u30E9\u30FC: \u30D5\u30A1\u30A4\u30EB{0}\u306E\u8AAD\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+ERR_CantDeleteFile=\u30A8\u30E9\u30FC: \u30D5\u30A1\u30A4\u30EB{0}\u306F\u524A\u9664\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002
+ERR_MissingDirectory=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u898B\u3064\u304B\u308A\u307E\u305B\u3093
+ERR_InvalidDirectory=\u7121\u52B9\u306A\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}
+ERR_EmptySourceDirectory=\u30BD\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u7A7A\u3067\u3059
+ERR_MissingJavaHome=\u30A8\u30E9\u30FC: Java\u30DB\u30FC\u30E0\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u4E0D\u660E\u3067\u3059\u3002
+ERR_MissingJavaFxHome=\u30A8\u30E9\u30FC: JavaFx\u30DB\u30FC\u30E0\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u4E0D\u660E\u3067\u3059\u3002
+ERR_JavacFailed=\u30A8\u30E9\u30FC: javac\u306E\u5B9F\u884C\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u7D42\u4E86\u30B3\u30FC\u30C9: {0}
+ERR_MakeAllJavacFailed=\u30A8\u30E9\u30FC: java\u30BD\u30FC\u30B9\u306E\u30B3\u30F3\u30D1\u30A4\u30EB\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+ERR_DeployFailed=\u30A8\u30E9\u30FC: \u30C7\u30D7\u30ED\u30A4\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+ERR_InvalidStoreFile=\u30A8\u30E9\u30FC: \u7121\u52B9\u306A\u30AD\u30FC\u30B9\u30C8\u30A2\u30FB\u30D5\u30A1\u30A4\u30EB: {0}
+ERR_SignFailed=\u30A8\u30E9\u30FC: \u7F72\u540D\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+ERR_MissingAppResources=\u30A8\u30E9\u30FC: \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3jar\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F
+ERR_NoEmbeddedDT=\u30A8\u30E9\u30FC: -includedt\u306B\u306F\u3001\u3053\u306E\u914D\u5E03\u306B\u542B\u307E\u308C\u3066\u3044\u306A\u3044Java Deployment Toolkit\u304C\u5FC5\u8981\u3067\u3059
+
+MSG_UpdatingJar=jar\u30D5\u30A1\u30A4\u30EB\u306E\u66F4\u65B0\u4E2D: {0}
+MSG_NoJREPackaged=\u30D1\u30C3\u30B1\u30FC\u30B8\u306FJRE\u306A\u3057\u3067\u63D0\u4F9B\u3059\u308B\u3088\u3046\u69CB\u6210\u3055\u308C\u3066\u3044\u307E\u3059\u3002
+MSG_UserProvidedJRE=\u6B21\u306B\u3042\u308B\u30D9\u30FC\u30B9JDK\u3092\u4F7F\u7528: {0}
+MSG_UseSystemJRE=\u30D9\u30FC\u30B9JDK\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u306F\u30B7\u30B9\u30C6\u30E0JRE\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+MSG_BundlerFailed=\u30A8\u30E9\u30FC: \u30D0\u30F3\u30C9\u30E9"{1}" ({0})\u304C\u30D0\u30F3\u30C9\u30EB\u306E\u751F\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002
+MSG_BundlerPlatformException=\u30D0\u30F3\u30C9\u30E9{0}\u306F\u3053\u306E\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u3067\u306E\u30D0\u30F3\u30C9\u30EB\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3066\u3044\u306A\u3044\u305F\u3081\u3001\u30D0\u30F3\u30C9\u30E9\u304C\u30B9\u30AD\u30C3\u30D7\u3055\u308C\u307E\u3057\u305F\u3002
+MSG_BundlerConfigException=\u69CB\u6210\u306E\u554F\u984C\u306E\u305F\u3081\u3001\u30D0\u30F3\u30C9\u30E9{0}\u304C\u30B9\u30AD\u30C3\u30D7\u3055\u308C\u307E\u3057\u305F: {1}  \n\u6B21\u306E\u4FEE\u6B63\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044: {2}
+MSG_BundlerConfigExceptionNoAdvice=\u69CB\u6210\u306E\u554F\u984C\u306E\u305F\u3081\u3001\u30D0\u30F3\u30C9\u30E9{0}\u304C\u30B9\u30AD\u30C3\u30D7\u3055\u308C\u307E\u3057\u305F: {1}
+MSG_BundlerRuntimeException={1}\u306E\u305F\u3081\u3001\u30D0\u30F3\u30C9\u30E9{0}\u304C\u5931\u6557\u3057\u307E\u3057\u305F
+MSG_JarNoSelfCopy=\u81EA\u8EAB\u3078\u306Ejar\u306E\u30B3\u30D4\u30FC\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3059: {0}
+MSG_EnterKeystorePassword=\u30AD\u30FC\u30B9\u30C8\u30A2\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044:
+MSG_EnterKeyPassword=%s\u306E\u9375\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/Bundle_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,39 @@
+MSG_Version=Java \u6253\u5305\u7A0B\u5E8F\u7248\u672C
+ERR_UnknownArgument=\u9519\u8BEF: \u672A\u77E5\u53C2\u6570: {0}
+ERR_UnknownCommand=\u9519\u8BEF: \u672A\u77E5\u547D\u4EE4: {0}
+ERR_UnknownReason=\u672A\u77E5\u539F\u56E0
+ERR_MissingArgument=\u9519\u8BEF: \u7F3A\u5C11\u53C2\u6570: {0}
+ERR_EmbedingLauncher=\u9519\u8BEF: \u7F3A\u5C11\u5D4C\u5165\u8D44\u6E90 [{0}]
+ERR_ContradictorySetting=\u9519\u8BEF: Ant \u811A\u672C\u6E05\u5355\u53C2\u6570 ''{0}'' \u4E0E Ant \u811A\u672C\u6570\u636E\u7C7B\u578B\u8BBE\u7F6E\u51B2\u7A81\u3002
+ERR_CreatingDirFailed=\u9519\u8BEF: \u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55 {0}
+ERR_CreatingFileFailed=\u9519\u8BEF: \u65E0\u6CD5\u521B\u5EFA\u6587\u4EF6 {0}
+ERR_CreatingTempFileFailed=\u9519\u8BEF: \u65E0\u6CD5\u521B\u5EFA\u4E34\u65F6\u6587\u4EF6
+ERR_CreatingJarFailed=\u9519\u8BEF: \u65E0\u6CD5\u521B\u5EFA jar \u6587\u4EF6 {0}
+ERR_FileCopyFailed=\u9519\u8BEF: \u65E0\u6CD5\u5C06\u6587\u4EF6\u590D\u5236\u5230\u76EE\u5F55 {0}
+ERR_FileReadFailed=\u9519\u8BEF: \u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6 {0}
+ERR_CantDeleteFile=\u9519\u8BEF: \u65E0\u6CD5\u5220\u9664\u6587\u4EF6 {0}\u3002
+ERR_MissingDirectory=\u7F3A\u5C11\u76EE\u5F55 {0}
+ERR_InvalidDirectory=\u76EE\u5F55 {0} \u65E0\u6548
+ERR_EmptySourceDirectory=\u6E90\u76EE\u5F55 {0} \u4E3A\u7A7A
+ERR_MissingJavaHome=\u9519\u8BEF: Java \u4E3B\u76EE\u5F55\u672A\u77E5\u3002
+ERR_MissingJavaFxHome=\u9519\u8BEF: JavaFx \u4E3B\u76EE\u5F55\u672A\u77E5\u3002
+ERR_JavacFailed=\u9519\u8BEF: javac \u6267\u884C\u5931\u8D25, \u9000\u51FA\u4EE3\u7801: {0}
+ERR_MakeAllJavacFailed=\u9519\u8BEF: java \u6E90\u7F16\u8BD1\u5931\u8D25
+ERR_DeployFailed=\u9519\u8BEF: \u90E8\u7F72\u5931\u8D25
+ERR_InvalidStoreFile=\u9519\u8BEF: \u65E0\u6548\u5BC6\u94A5\u5E93\u6587\u4EF6: {0}
+ERR_SignFailed=\u9519\u8BEF: \u7B7E\u540D\u5931\u8D25
+ERR_MissingAppResources=\u9519\u8BEF: \u627E\u4E0D\u5230\u5E94\u7528\u7A0B\u5E8F jar
+ERR_NoEmbeddedDT=\u9519\u8BEF: -includedt \u9700\u8981 java \u90E8\u7F72\u5DE5\u5177\u5305, \u4F46\u6B64\u5206\u53D1\u4E2D\u672A\u5305\u542B
+
+MSG_UpdatingJar=\u66F4\u65B0 Jar \u6587\u4EF6: {0}
+MSG_NoJREPackaged=\u7A0B\u5E8F\u5305\u914D\u7F6E\u4E3A\u5728\u53D1\u8FD0\u65F6\u4E0D\u5E26 JRE\u3002
+MSG_UserProvidedJRE=\u4F7F\u7528\u4EE5\u4E0B\u4F4D\u7F6E\u7684\u57FA\u7840 JDK: {0}
+MSG_UseSystemJRE=\u6CA1\u6709\u57FA\u7840 JDK\u3002\u7A0B\u5E8F\u5305\u5C06\u4F7F\u7528\u7CFB\u7EDF JRE\u3002
+MSG_BundlerFailed=\u9519\u8BEF: \u6253\u5305\u7A0B\u5E8F "{1}" ({0}) \u65E0\u6CD5\u751F\u6210\u5305\u3002
+MSG_BundlerPlatformException=\u7531\u4E8E\u6253\u5305\u7A0B\u5E8F{0}\u4E0D\u652F\u6301\u5728\u6B64\u5E73\u53F0\u4E0A\u6253\u5305, \u56E0\u6B64\u5C06\u5176\u8DF3\u8FC7\u3002
+MSG_BundlerConfigException=\u7531\u4E8E\u914D\u7F6E\u95EE\u9898, \u8DF3\u8FC7\u4E86\u6253\u5305\u7A0B\u5E8F{0}: {1}  \n\u4FEE\u590D\u5EFA\u8BAE: {2}
+MSG_BundlerConfigExceptionNoAdvice=\u7531\u4E8E\u914D\u7F6E\u95EE\u9898, \u8DF3\u8FC7\u4E86\u6253\u5305\u7A0B\u5E8F{0}: {1}
+MSG_BundlerRuntimeException=\u7531\u4E8E{1}, \u6253\u5305\u7A0B\u5E8F{0}\u5931\u8D25
+MSG_JarNoSelfCopy=\u8DF3\u8FC7 jar \u590D\u5236\u5230\u81EA\u8EAB: {0}
+MSG_EnterKeystorePassword=\u8F93\u5165\u5BC6\u94A5\u5E93\u7684\u5BC6\u7801\u77ED\u8BED:
+MSG_EnterKeyPassword=\u8F93\u5165%s\u7684\u5BC6\u94A5\u53E3\u4EE4:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/CLIHelp.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,165 @@
+MSG_Help_common=Usage: jpackager <mode> <options>\n\
+\n\
+where mode is one of: \n\
+\  create-image\n\
+\          Generates a platform-specific application image.\n\
+\  create-installer <type>\n\
+\          Generates a platform-specific installer for the application.\n\
+\          Valid values for "type" are "msi", "rpm", "deb", "dmg", \u201cpkg\u201d,\n\
+\          \u201cpkg-app-store\u201d. If "type" is omitted, all supported types of installable\n\
+\          packages for current platform will be generated.\n\
+\  create-jre-installer <type>\n\
+\          Generates a platform-specific installer for Server JRE.\n\
+\          Valid values for "type" are "msi", "rpm", "deb", "dmg", \u201cpkg\u201d.\n\
+\          If "type" is omitted, all supported types of installable packages\n\
+\          for current platform will be generated.\n\
+\          \n\
+Sample usages:\n\
+--------------\n\
+jpackager create-image --input inputdir --output outputdir --name AppName --class package.ClassName\n\
+or\n\
+jpackager create-image -i inputdir -o outputdir -n AppName -c package.ClassName\n\
+Generates an application image.\n\
+\n\
+jpackager create-installer -i inputdir -o outputdir -n "App Name" -c package.ClassName\n\
+Generates an application installer.\n\
+\n\
+jpackager create-jre-installer -n <jre_name> -o outputdir\n\
+Generates a Server JRE installer.\n\
+\n\
+The following options are valid for all platforms:\n\
+\  --output -o\n\
+\          Name of the directory where generated output file is placed.\n\
+\  --input -i\n\
+\          Name of the base directory that contains the files to package.\n\
+\  --files -f\n\
+\          List of files in the base directory. If omitted, all files from "input"\n\
+\          directory (which is a mandatory argument in this case) will be packaged.\n\
+\  --name -n\n\
+\          Name of the application.\n\
+\  --main-jar -j\n\
+\          The main JAR of the application. This JAR should have the main-class,\n\
+\          and is relative to the assembled application directory.\n\
+\  --class -c\n\
+\          Qualified name of the application class to execute.\n\
+\  --version -v\n\
+\          Version of the application.\n\
+\  --arguments -a\n\
+\          Command line arguments to pass to the main class if no arguments\n\
+\          are specified by the launcher.\n\
+\  --icon\n\
+\          Icon of the application bundle.\n\
+\  --singleton\n\
+\          Prevents multiple instances of the application from launching\n\
+\          (see SingleInstanceService API for more details).\n\
+\  --identifier\n\
+\          Machine readable identifier of the application. The format\n\
+\          must be a DNS name in reverse order, such as com.example.myapplication.\n\
+\          The identifier is used for composing Single Instance unique id and\n\
+\          calculating preferences node to search for User JVM Options\n\
+\          (the format is a slash delimited version of the main package name,\n\
+\          such as "com/example/myapplication"), see UserJvmOptionsService API\n\
+\          for more details.\n\
+\  --verbose\n\
+\          Enables verbose output.\n\
+\  --strip-native-commands\n\
+\          Removes native executables from the custom run-time images.\n\
+\  --jvm-args\n\
+\          JVM flags and options to pass to the application.\n\
+\  --user-jvm-args\n\
+\          JVM options the user may override along and their default values\n\
+\          (see UserJvmOptionsService API for more details).\n\
+\  --file-associations\n\
+\          Properties file that contains list of key=value parameters that\n\
+\          describe a file association. "extension", "mime-type", "icon",\n\
+\          "description" can be used as keys for the association.\n\
+\  --secondary-launcher\n\
+\          Properties file that contains a collection of options for a secondary launcher.\n\
+\  --build-root\n\
+\          Directory in which to use and place temporary files.\n\
+\  --runtime-image\n\
+\          Location of the predefined runtime image that is used to build\n\
+\          an application image and installable package.\n\
+\  --app-image\n\
+\          Location of the predefined application image that is used to build\n\
+\          an installable package.\n\
+\  --install-dir\n\
+\          Installation directory of the application. Ignored on Windows, use\n\
+\          \u2013-win-dir-chooser to provide an ability to choose an installation directory.\n\
+\  --echo-mode\n\
+\          Outputs (without executing) native packaging commands so that users\n\
+\          can use this as a starting point for addressing more complex needs.\n\
+\  --license-file\n\
+\          The license file, relative to the base directory.\n\
+\  --copyright\n\
+\          Copyright for the application.\n\
+\  --description\n\
+\          Description of the application.\n\
+\  --category\n\
+\          Category or group of the application.\n\
+\  --vendor\n\
+\          Vendor of the application.\n\
+\n\
+Modular options:\n\
+\  --module -m\n\
+\          Main module of the application. This module must have the main-class,\n\
+\          and be on the module path.\n\
+\  --module-path -p\n\
+\          When packaging the Java Runtime, this is the path JLink looks in for modules.\n\
+\  --add-modules\n\
+\          List of modules to add to JImage creation, including possible services.\n\
+\  --limit-modules\n\
+\          Modules to limit JImage creation to.\n\
+
+MSG_Help_mac=\nThe following options are valid for Mac OS X platforms:\n\
+\  --mac-sign\n\
+\          Request that the bundle be signed.\n\
+\  --mac-bundle-name\n\
+\          Name of the application as it appears in the Menu Bar. This can be\n\
+\          different from the application name. This name must be less than 16\n\
+\          characters long and be suitable for displaying in the menu bar and\n\
+\          the application Info window.\n\
+\  --mac-bundle-identifier\n\
+\          An identifier that uniquely identifies the application for MacOSX\n\
+\          (and on the Mac App Store).  May only use alphanumeric (A-Z,a-z,0-9),\n\
+\          hyphen (-), and period (.) characters.\n\
+\  --mac-app-store-category\n\
+\          Mac App Store Categories. Note that the key is the string shown to\n\
+\          the user and the value is the ID of the category.\n\
+\  --mac-app-store-entitlements\n\
+\          File location of a custom mac app store entitlements file.\n\
+\  --mac-bundle-signing-prefix\n\
+\          When signing the application bundle, this value is prefixed to all\n\
+\          components that need to be signed that don't have an existing bundle identifier.\n\
+\  --mac-signing-key-user-name\n\
+\          User name portion of the typical "Mac Developer ID Application: <user name>" signing key.\n\
+\  --mac-signing-keychain\n\
+\          Location of the keychain to use. If not specified, the standard keychains are used.\n\
+
+MSG_Help_linux=\nThe following options are valid for Linux platforms:\n\
+\  --linux-bundle-name\n\
+\          Name for Linux bundle.\n\
+\  --linux-package-deps\n\
+\          Required packages or capabilities for the application.\n\
+\  --linux-rpm-license-type\n\
+\          Type of the license ("License: <value>" of the RPM .spec).\n\
+\  --linux-deb-maintainer\n\
+\          Maintainer for .deb bundle.\n\
+
+MSG_Help_win=\nThe following options are valid for Windows platforms:\n\
+\  --win-menu\n\
+\          Adds the application to the system menu.\n\
+\  --win-menu-group\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-dir-chooser\n\
+\          Adds a dialog to enable the user to choose a directory in which\n\
+\          the product is installed.\n\
+\  --win-registry-name\n\
+\          Name of the application for registry references. Default is\n\
+\          the Application Name with only alphanumerics, dots, and dashes (no whitespace).\n\
+\  --win-upgrade-uuid\n\
+\          UUID associated with upgrades for this package.\n\
+\  --win-shortcut\n\
+\          Creates a desktop shortcut for the application.\n\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/JLinkBundlerHelper.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,17 @@
+param.detect-modules.name=Auto Modules
+param.detect-modules.description=Automatically calculate modules to Limit JImage creation to.
+
+param.jlink-options.name=JLink Options
+param.jlink-options.description=Options to be added to JLink invocation.
+
+param.jlink-builder.name=JLink Builder
+param.jlink-builder.description=Name of the JLink Builder to build the applicaiton image with.
+
+error.srcfiles.contain.modules=Error: Modules are not allowed in srcfiles: {0}.
+
+warning.module.does.not.exist=Module {0} does not exist.
+
+message.detected.modules="Automatically adding detected modules: {0}."
+message.modules="Adding modules: {0} to runtime image."
+
+using.experimental.feature="Using experimental feature: {0}."
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/JLinkBundlerHelper_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,17 @@
+param.detect-modules.name=\u81EA\u52D5\u30E2\u30B8\u30E5\u30FC\u30EB
+param.detect-modules.description=JImage\u306E\u4F5C\u6210\u3092\u5236\u9650\u3059\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u81EA\u52D5\u7684\u306B\u8A08\u7B97\u3057\u307E\u3059\u3002
+
+param.jlink-options.name=JLink\u30AA\u30D7\u30B7\u30E7\u30F3
+param.jlink-options.description=JLink\u306E\u8D77\u52D5\u306B\u8FFD\u52A0\u3055\u308C\u308B\u30AA\u30D7\u30B7\u30E7\u30F3
+
+param.jlink-builder.name=JLink\u30D3\u30EB\u30C0\u30FC
+param.jlink-builder.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u3092\u4F5C\u6210\u3059\u308BJLink\u30D3\u30EB\u30C0\u30FC\u306E\u540D\u524D
+
+error.srcfiles.contain.modules=\u30A8\u30E9\u30FC: \u30E2\u30B8\u30E5\u30FC\u30EB\u306Fsrcfiles\u3067\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093: {0}\u3002
+
+warning.module.does.not.exist=\u30E2\u30B8\u30E5\u30FC\u30EB{0}\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002
+
+message.detected.modules="\u691C\u51FA\u3055\u308C\u305F\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u81EA\u52D5\u7684\u306B\u8FFD\u52A0\u3057\u3066\u3044\u307E\u3059: {0}."
+message.modules="\u30E2\u30B8\u30E5\u30FC\u30EB: {0}\u3092\u30E9\u30F3\u30BF\u30A4\u30E0\u30FB\u30A4\u30E1\u30FC\u30B8\u306B\u8FFD\u52A0\u3057\u3066\u3044\u307E\u3059\u3002"
+
+using.experimental.feature="\u8A66\u9A13\u7684\u306A\u6A5F\u80FD\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059: {0}\u3002"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/JLinkBundlerHelper_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,17 @@
+param.detect-modules.name=\u81EA\u52A8\u6A21\u5757
+param.detect-modules.description=\u81EA\u52A8\u8BA1\u7B97\u6A21\u5757\u4EE5\u5C06 JImage \u521B\u5EFA\u64CD\u4F5C\u9650\u5236\u4E3A\u8FD9\u4E9B\u6A21\u5757\u3002
+
+param.jlink-options.name=JLink \u9009\u9879
+param.jlink-options.description=\u8981\u6DFB\u52A0\u5230 JLink \u8C03\u7528\u7684\u9009\u9879\u3002
+
+param.jlink-builder.name=JLink Builder
+param.jlink-builder.description=\u7528\u4E8E\u6784\u5EFA\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\u7684 JLink Builder \u7684\u540D\u79F0\u3002
+
+error.srcfiles.contain.modules=\u9519\u8BEF: srcfile \u4E2D\u4E0D\u5141\u8BB8\u6A21\u5757: {0}\u3002
+
+warning.module.does.not.exist=\u6A21\u5757 {0} \u4E0D\u5B58\u5728\u3002
+
+message.detected.modules="\u6B63\u5728\u81EA\u52A8\u6DFB\u52A0\u68C0\u6D4B\u5230\u7684\u6A21\u5757: {0}\u3002"
+message.modules="\u6B63\u5728\u5C06\u6A21\u5757 {0} \u6DFB\u52A0\u5230\u8FD0\u884C\u65F6\u6620\u50CF\u3002"
+
+using.experimental.feature="\u6B63\u5728\u4F7F\u7528\u8BD5\u9A8C\u529F\u80FD: {0}\u3002"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/StandardBundlerParam.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,190 @@
+param.app-name.name=App Name
+param.app-name.description=The name of the application.
+
+param.app-fs-name.name=App File System Name
+param.app-fs-name.description=The name of the application suitable for file system use.  Typically this is just letters, numbers, dots, and dashes.
+
+param.app-resource.description=All of the files to place in the resources directory.  Including all needed jars as assets.
+param.app-resources.name=Resources
+
+param.app-resource-list.description=A List of RelativeFileSet objects containing all of the files to place in the resources directory.  Including all needed jars as assets.
+param.app-resources-list.name=Resources List
+
+param.build-root.name=Build Root
+param.build-root.description=The directory in which to use and place temporary files.
+
+param.category.name=Category
+param.category.description=The category oor group of the application.  Generally speaking you will also want to specify application specific categories as well.
+param.category.default=Unknown
+
+param.copyright.name=Copyright
+param.copyright.description=The copyright for the application.
+param.copyright.default=Copyright (C) {0,date,YYYY}
+
+param.description.name=Description
+param.description.description=A longer description of the application
+param.description.default=none
+
+param.icon-file.name=Icon
+param.icon-file.description=The main icon of the application bundle.
+
+param.identifier.name=Identifier
+param.identifier.description=What is the machine readable identifier of this application?  The format should be a DNS name in reverse order, such as com.example.myapplication.
+
+param.arguments.name=Command Line Arguments
+param.arguments.description=Command Line Arguments to be passed to the main class if no arguments are specified by the launcher.
+
+param.jvm-options.name=JVM Options
+param.jvm-options.description=JVM flags and options to be passed in.
+
+param.jvm-system-properties.name=JVM System Properties
+param.jvm-system-properties.description=JVM System Properties (of the -Dname\=value variety).
+
+param.license-file.name=License
+param.license-file.description=The license file, relative to the assembled application directory.
+
+param.source-files.name=Files
+param.source-files.description=Set of files from input directory to be bundled.
+
+param.main-class.name=Main Class
+param.main-class.description=The main class for the application.  Either a javafx.application.Application instance or a java class with a main method.
+
+param.main-module.name=Main Module
+param.main-module.description=The main module for the application.  This is the module containing the main class.
+
+param.classpath.name=Main Jar Classpath
+param.classpath.description=The classpath from the main jar of the application, relative to the assembled application directory.
+
+param.main-jar.name=Main Jar
+param.main-jar.description=The main jar of the application.  This jar should have the main-class, and is relative to the assembled application dir.
+
+param.service-hint.name=Service Hint
+param.service-hint.description=The bundler should register the application as service/daemon
+
+param.start-on-install.name=Start On Install
+param.start-on-install.description=Controls whether the service/daemon should be started on install
+
+param.stop-on-uninstall.name=Stop On Uninstall
+param.stop-on-uninstall.description=Controls whether the service/daemon should be stopped on uninstall
+
+param.run-at-startup.name=Run At Startup
+param.run-at-startup.description=Controls whether the service/daemon should be started during system startup
+
+param.name.name=Name
+param.name.description=The name of the application.
+
+param.preferences-id.name=Preferences ID
+param.preferences-id.description=The preferences node to search for User JVM Options.  The format be a slash delimited version of the main package name, such as "com/example/myapplication".
+
+param.preloader.name=JavaFX Preloader Class Name
+param.preloader.description=For JavaFX applications only, this is the Fully Qualified Class Name of the preloader class.  This class needs to exist in the classpath, preferably early in the path.
+
+param.runtime.name=JRE
+param.runtime.description=The Java Runtime to co-bundle.  The default value is the current JRE running the bundler.  A value of null will cause no JRE to be co-bundled and the system JRE will be used to launch the application.
+
+param.title.name=Title
+param.title.description=A title for the application.
+
+param.use-javafx-packaging.name=FX Packaging
+param.use-javafx-packaging.description=Should we use the JavaFX packaging conventions?
+
+param.user-jvm-options.name=User JVM Options
+param.user-jvm-options.description=JVM Options the user may override, along with their default values.
+
+param.vendor.name=Vendor
+param.vendor.description=The vendor of the application.
+param.vendor.default=Unknown
+
+param.predefined-app-image.name=Predefined Application Image
+param.predefined-app-image.description=Location of the predefined application image that is used to build an installable package.
+
+param.predefined-runtime-image.name=Predefined Runtime Image
+param.predefined-runtime-image.description=Location of the custom runtime image that is used to build an application image and installable packages.
+
+param.version.name=Version
+param.version.description=The version of this application.
+param.version.default=1.0
+
+param.verbose.name=Verbose
+param.verbose.description=Flag to print out more information and saves configuration files for bundlers.
+
+param.drop-in-resources-root.name=Drop-In Resources Root
+param.drop-in-resources-root.description=The directory to look for bundler specific drop in resources.  If not set the classpath will be searched.
+
+param.secondary-launchers.name=Secondary Launchers
+param.secondary-launchers.description=A collection of bundle param info for secondary launchers
+
+param.file-associations.name=File Associations
+param.file-associations.description=A list of maps where each map describes a file association.  Uses the "fileAssociation." series of bundle arguments in each map.
+
+param.fa-extension.name=File Association Extension
+param.fa-extension.description=The File Extension to be associated, just the extension no dots.
+
+param.fa-content-type.name=File Association Content Type
+param.fa-content-type.description=Content Type to be associated.  Such as application/x-vnd.my-awesome-app.
+
+param.fa-icon.name=File Association Icon
+param.fa-icon.description=The Icon to be used for associated files.  Defaults to the application icon.
+
+param.fa-description.name=File Association Description
+param.fa-description.description=The description to be used for associated files.  The default is "<appName> File".
+
+param.commercial-features.name=Unlock Commercial Features
+param.commercial-features.description=Some options require commercial features to be unlocked.  This must be passed in as true to unlock those features.  Otherwise they will be ignored.
+
+param.com-app-cds.name=Enable AppCDS
+param.com-app-cds.description=Enabled and package with Application Class Data Sharing, including generation of .jsa file.
+
+param.com-app-cds-cache-mode.name=AppCDS Cache Mode
+param.com-app-cds-cache-mode.description=The mode in which the AppCDS .jpa files are generated and cached.  Current values are 'install', 'auto', and 'auto+install'.
+
+param.com-app-cds-root.name=AppCDS Root Classes
+param.com-app-cds-root.description=List of "root classes" for AppCDS to generate class sharing data from.  Default is the main class.
+
+param.source-dir.name=Source Directory
+param.source-dir.description=Path to the directory containing the files to be bundled.
+
+param.module-path.name=Module Path
+param.module-path.description=When packaging the Java Runtime, this is the path JLink will look in for modules.
+
+param.add-modules.name=Add Modules
+param.add-modules.description=List of Modules to add to JImage creation, including possible services.
+
+param.limit-modules.name=Limit Modules
+param.limit-modules.description=Modules to Limit JImage creation to.
+
+param.strip-executables.name=Strip Native Executables
+param.strip-executables.description=Removes native executables from the JImage creation.
+
+param.main.module.name=Main Module
+param.main.module.description=The main module of the application.  This module should have the main-class, and is on the module path.
+
+param.singleton.name=Singleton
+param.singleton.description=Prevents from launching multiple instances of application.
+
+param.install-dir.name=Installation Directory
+param.install-dir.description=Installation directory of the application.
+
+param.echo-mode.name=Echo Mode
+param.echo-mode.description=Outputs (without executing) native packaging commands so that users can use this as a starting point for addressing more complex needs.
+
+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
+
+error.required-parameter={0} is a required parameter.
+error.no-main-class-with-main-jar=An application class was not specified nor was one found in the jar {0}
+error.no-main-class-with-main-jar.advice=Please specify a applicationClass or ensure that the jar {0} specifies one in the manifest.
+error.no-main-class-with-classpath=An application class was not specified nor was one found in the supplied classpath
+error.no-main-class-with-classpath.advice=Please specify a applicationClass or ensure that the classpath has a jar containing one in the manifest.
+error.no-main-class=An application class was not specified nor was one found in the supplied application resources
+error.no-main-class.advice=Please specify a applicationClass 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}
+error.main-jar-does-not-exist.advice=The main jar must be specified relative to the app resources (not an absolute path), and must exist within those resources.
+
+message.fx-app-does-not-match-specified-main=The jar {0} has an FX Application class{1} that does not match the declared main {2}
+message.main-class-does-not-match-specified-main=The jar {0} has a main class {1} that does not match the declared main {2}
+
+warning.no.jdk.modules.found=Warning: No JDK Modules found.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/StandardBundlerParam_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,182 @@
+param.app-name.name=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D
+param.app-name.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u540D\u524D\u3002
+
+param.app-fs-name.name=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D5\u30A1\u30A4\u30EB\u30FB\u30B7\u30B9\u30C6\u30E0\u540D
+param.app-fs-name.description=\u30D5\u30A1\u30A4\u30EB\u30FB\u30B7\u30B9\u30C6\u30E0\u306E\u4F7F\u7528\u306B\u9069\u3057\u305F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u540D\u524D\u3002\u4E00\u822C\u7684\u306B\u3001\u5358\u306B\u6587\u5B57\u3001\u6570\u5024\u3001\u30C9\u30C3\u30C8\u304A\u3088\u3073\u30C0\u30C3\u30B7\u30E5\u3067\u3059\u3002
+
+param.app-resource.description=\u30EA\u30BD\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u914D\u7F6E\u3059\u308B\u3059\u3079\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u3002\u30A2\u30BB\u30C3\u30C8\u3068\u3057\u3066\u5FC5\u8981\u306A\u3059\u3079\u3066\u306Ejar\u3092\u542B\u3081\u3066\u3044\u307E\u3059\u3002
+param.app-resources.name=\u30EA\u30BD\u30FC\u30B9
+
+param.app-resource-list.description=\u30EA\u30BD\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u914D\u7F6E\u3059\u308B\u3059\u3079\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u542B\u3080RelativeFileSet\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30EA\u30B9\u30C8\u3002\u30A2\u30BB\u30C3\u30C8\u3068\u3057\u3066\u5FC5\u8981\u306A\u3059\u3079\u3066\u306Ejar\u3092\u542B\u3081\u3066\u3044\u307E\u3059\u3002
+param.app-resources-list.name=\u30EA\u30BD\u30FC\u30B9\u30FB\u30EA\u30B9\u30C8
+
+param.build-root.name=\u4F5C\u6210\u30EB\u30FC\u30C8
+param.build-root.description=\u4E00\u6642\u30D5\u30A1\u30A4\u30EB\u3092\u4F7F\u7528\u304A\u3088\u3073\u914D\u7F6E\u3059\u308B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3002
+
+param.category.name=\u30AB\u30C6\u30B4\u30EA
+param.category.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30AB\u30C6\u30B4\u30EA\u307E\u305F\u306F\u30B0\u30EB\u30FC\u30D7\u3002\u4E00\u822C\u7684\u306B\u3001\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u56FA\u6709\u306E\u30AB\u30C6\u30B4\u30EA\u3082\u6307\u5B9A\u3057\u307E\u3059\u3002
+param.category.default=\u4E0D\u660E
+
+param.copyright.name=\u30B3\u30D4\u30FC\u30E9\u30A4\u30C8 
+param.copyright.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30B3\u30D4\u30FC\u30E9\u30A4\u30C8\u3002
+param.copyright.default=Copyright (C) {0,date,YYYY}
+
+param.description.name=\u8AAC\u660E
+param.description.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u8A73\u7D30\u306A\u8AAC\u660E
+param.description.default=\u306A\u3057
+
+param.desktop-shortcut-hint.name=\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u306E\u30D2\u30F3\u30C8
+param.desktop-shortcut-hint.description=\u30D0\u30F3\u30C9\u30E9\u304C\u30C7\u30B9\u30AF\u30C8\u30C3\u30D7\u30FB\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u4F5C\u6210\u3067\u304D\u308B\u5834\u5408\u3001\u4F5C\u6210\u3057\u307E\u3059\u304B\u3002
+
+param.icon-file.name=\u30A2\u30A4\u30B3\u30F3
+param.icon-file.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB\u306E\u30E1\u30A4\u30F3\u30FB\u30A2\u30A4\u30B3\u30F3\u3002
+
+param.identifier.name=\u8B58\u5225\u5B50
+param.identifier.description=\u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30DE\u30B7\u30F3\u3067\u8AAD\u53D6\u308A\u53EF\u80FD\u306A\u8B58\u5225\u5B50\u306F\u4F55\u3067\u3059\u304B\u3002\u5F62\u5F0F\u306F\u3001com.example.myapplication\u306A\u3069\u3001DNS\u540D\u306E\u9006\u9806\u306B\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
+
+param.arguments.name=\u30B3\u30DE\u30F3\u30C9\u30E9\u30A4\u30F3\u5F15\u6570
+param.arguments.description=\u5F15\u6570\u304C\u30E9\u30F3\u30C1\u30E3\u306B\u3088\u3063\u3066\u6307\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u306B\u3001\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u306B\u6E21\u3055\u308C\u308B\u30B3\u30DE\u30F3\u30C9\u30E9\u30A4\u30F3\u5F15\u6570\u3002
+
+param.jvm-options.name=JVM\u30AA\u30D7\u30B7\u30E7\u30F3
+param.jvm-options.description=\u6E21\u3055\u308C\u308BJVM\u30D5\u30E9\u30B0\u304A\u3088\u3073\u30AA\u30D7\u30B7\u30E7\u30F3\u3002
+
+param.jvm-system-properties.name=JVM\u30B7\u30B9\u30C6\u30E0\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3
+param.jvm-system-properties.description=(\u5404\u7A2E-Dname=value\u306E)JVM\u30B7\u30B9\u30C6\u30E0\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u3002
+
+param.license-file.name=\u30E9\u30A4\u30BB\u30F3\u30B9
+param.license-file.description=\u30E9\u30A4\u30BB\u30F3\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3001\u30A2\u30BB\u30F3\u30D6\u30EB\u3055\u308C\u305F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u5BFE\u3057\u3066\u76F8\u5BFE\u7684\u3067\u3059\u3002
+
+param.license-type.name=
+param.license-type.description=
+param.license-type.default=\u4E0D\u660E
+
+param.main-class.name=\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9
+param.main-class.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u3002javafx.application.Application\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u307E\u305F\u306Fmain\u30E1\u30BD\u30C3\u30C9\u3092\u542B\u3080Java\u30AF\u30E9\u30B9\u3002
+
+param.main-module.name=\u30E1\u30A4\u30F3\u30FB\u30E2\u30B8\u30E5\u30FC\u30EB
+param.main-module.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30E1\u30A4\u30F3\u30FB\u30E2\u30B8\u30E5\u30FC\u30EB\u3002\u3053\u308C\u306F\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u3092\u542B\u3080\u30E2\u30B8\u30E5\u30FC\u30EB\u3067\u3059\u3002
+
+param.classpath.name=\u30E1\u30A4\u30F3Jar\u306E\u30AF\u30E9\u30B9\u30D1\u30B9
+param.classpath.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30E1\u30A4\u30F3jar\u304B\u3089\u306E\u30AF\u30E9\u30B9\u30D1\u30B9\u3067\u3001\u30A2\u30BB\u30F3\u30D6\u30EB\u3055\u308C\u305F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u5BFE\u3057\u3066\u76F8\u5BFE\u7684\u3067\u3059\u3002
+
+param.main-jar.name=\u30E1\u30A4\u30F3Jar
+param.main-jar.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30E1\u30A4\u30F3jar\u3002\u3053\u306Ejar\u306Fmain-class\u3092\u6301\u3064\u5FC5\u8981\u304C\u3042\u308A\u3001\u30A2\u30BB\u30F3\u30D6\u30EB\u3055\u308C\u305F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u5BFE\u3057\u3066\u76F8\u5BFE\u7684\u3067\u3059\u3002
+
+param.service-hint.name=\u30B5\u30FC\u30D3\u30B9\u306E\u30D2\u30F3\u30C8
+param.service-hint.description=\u30D0\u30F3\u30C9\u30E9\u306F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u30B5\u30FC\u30D3\u30B9/\u30C7\u30FC\u30E2\u30F3\u3068\u3057\u3066\u767B\u9332\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
+
+param.start-on-install.name=\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u6642\u306B\u8D77\u52D5
+param.start-on-install.description=\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u6642\u306B\u30B5\u30FC\u30D3\u30B9/\u30C7\u30FC\u30E2\u30F3\u3092\u8D77\u52D5\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u304B\u3069\u3046\u304B\u3092\u5236\u5FA1\u3057\u307E\u3059
+
+param.stop-on-uninstall.name=\u30A2\u30F3\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u6642\u306B\u505C\u6B62
+param.stop-on-uninstall.description=\u30A2\u30F3\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u6642\u306B\u30B5\u30FC\u30D3\u30B9/\u30C7\u30FC\u30E2\u30F3\u3092\u505C\u6B62\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u304B\u3069\u3046\u304B\u3092\u5236\u5FA1\u3057\u307E\u3059
+
+param.run-at-startup.name=\u8D77\u52D5\u6642\u306B\u5B9F\u884C
+param.run-at-startup.description=\u30B7\u30B9\u30C6\u30E0\u8D77\u52D5\u6642\u306B\u30B5\u30FC\u30D3\u30B9/\u30C7\u30FC\u30E2\u30F3\u3092\u8D77\u52D5\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u304B\u3069\u3046\u304B\u3092\u5236\u5FA1\u3057\u307E\u3059
+
+param.sign-bundle.name=\u7F72\u540D\u30D0\u30F3\u30C9\u30EB
+param.sign-bundle.description=\u30D0\u30F3\u30C9\u30E9\u304C\u7F72\u540D\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3066\u3044\u308B\u5834\u5408\u3001\u30D0\u30F3\u30C9\u30EB\u304C\u7F72\u540D\u3055\u308C\u3066\u3044\u308B\u3053\u3068\u3092\u8981\u6C42\u3057\u307E\u3059\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u306F\u30D0\u30F3\u30C9\u30E9\u306B\u3088\u3063\u3066\u7570\u306A\u308A\u307E\u3059\u3002\u7F72\u540D\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u3066\u3044\u306A\u3044\u30D0\u30F3\u30C9\u30E9\u3067\u306F\u3001\u3053\u306E\u8A2D\u5B9A\u306F\u8B66\u544A\u306A\u3057\u3067\u7121\u8996\u3055\u308C\u307E\u3059\u3002
+
+param.menu-shortcut-hint.name=\u30E1\u30CB\u30E5\u30FC\u306E\u30D2\u30F3\u30C8
+param.menu-shortcut-hint.description=\u30D0\u30F3\u30C9\u30E9\u304C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u30B7\u30B9\u30C6\u30E0\u30FB\u30E1\u30CB\u30E5\u30FC\u306B\u8FFD\u52A0\u3067\u304D\u308B\u5834\u5408\u3001\u5B9F\u884C\u3057\u307E\u3059\u304B\u3002
+
+param.name.name=\u540D\u524D
+param.name.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u540D\u524D\u3002
+
+param.preferences-id.name=\u30D7\u30EA\u30D5\u30A1\u30EC\u30F3\u30B9ID
+param.preferences-id.description=\u30E6\u30FC\u30B6\u30FC\u306EJVM\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u691C\u7D22\u3059\u308B\u30D7\u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u30FB\u30CE\u30FC\u30C9\u3002\u5F62\u5F0F\u306F\u3001"com/example/myapplication"\u306A\u3069\u3001\u30E1\u30A4\u30F3\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u540D\u306E\u30B9\u30E9\u30C3\u30B7\u30E5\u533A\u5207\u308A\u30D0\u30FC\u30B8\u30E7\u30F3\u3067\u3059\u3002
+
+param.preloader.name=JavaFX\u30D7\u30EC\u30ED\u30FC\u30C0\u30FC\u30FB\u30AF\u30E9\u30B9\u540D
+param.preloader.description=JavaFX\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u307F\u306E\u5834\u5408\u3001\u30D7\u30EC\u30ED\u30FC\u30C0\u30FC\u30FB\u30AF\u30E9\u30B9\u306E\u5B8C\u5168\u4FEE\u98FE\u540D\u3067\u3059\u3002\u3053\u306E\u30AF\u30E9\u30B9\u306F\u30AF\u30E9\u30B9\u30D1\u30B9(\u53EF\u80FD\u306A\u5834\u5408\u306F\u30D1\u30B9\u306E\u524D\u306E\u65B9)\u306B\u5B58\u5728\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
+
+param.runtime.name=JRE
+param.runtime.description=\u30D0\u30F3\u30C9\u30EB\u3059\u308BJava\u30E9\u30F3\u30BF\u30A4\u30E0\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u306F\u3001\u30D0\u30F3\u30C9\u30E9\u3092\u5B9F\u884C\u3057\u3066\u3044\u308B\u73FE\u5728\u306EJRE\u3067\u3059\u3002\u5024\u304Cnull\u306E\u5834\u5408\u3001JRE\u306F\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305A\u3001\u30B7\u30B9\u30C6\u30E0\u306EJRE\u304C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u8D77\u52D5\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+
+param.system-wide.name=\u30B7\u30B9\u30C6\u30E0\u5168\u4F53
+param.system-wide.description=\u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306F\u3001\u305D\u308C\u81EA\u4F53\u3092\u30B7\u30B9\u30C6\u30E0\u5168\u4F53\u306B\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u307E\u3059\u304B\u3001\u307E\u305F\u306F\u5404\u30E6\u30FC\u30B6\u30FC\u306B\u5BFE\u3057\u3066\u306E\u307F\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u307E\u3059\u304B\u3002Null\u306F\u30B7\u30B9\u30C6\u30E0\u30FB\u30C7\u30D5\u30A9\u30EB\u30C8\u3092\u4F7F\u7528\u3059\u308B\u3053\u3068\u3092\u610F\u5473\u3057\u307E\u3059\u3002
+
+param.title.name=\u30BF\u30A4\u30C8\u30EB
+param.title.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30BF\u30A4\u30C8\u30EB\u3002
+
+param.use-javafx-packaging.name=FX\u30D1\u30C3\u30B1\u30FC\u30B8\u30F3\u30B0
+param.use-javafx-packaging.description=JavaFX\u30D1\u30C3\u30B1\u30FC\u30B8\u30F3\u30B0\u898F\u5247\u3092\u4F7F\u7528\u3057\u307E\u3059\u304B\u3002
+
+param.user-jvm-options.name=\u30E6\u30FC\u30B6\u30FC\u306EJVM\u30AA\u30D7\u30B7\u30E7\u30F3
+param.user-jvm-options.description=\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u306B\u52A0\u3048\u3066\u3001\u30E6\u30FC\u30B6\u30FC\u304C\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3067\u304D\u308BJVM\u30AA\u30D7\u30B7\u30E7\u30F3\u3002
+
+param.vendor.name=\u30D9\u30F3\u30C0\u30FC
+param.vendor.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30D9\u30F3\u30C0\u30FC\u3002
+param.vendor.default=\u4E0D\u660E
+
+param.version.name=\u30D0\u30FC\u30B8\u30E7\u30F3
+param.version.description=\u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3002
+param.version.default=1.0
+
+param.verbose.name=\u8A73\u7D30
+param.verbose.description=\u8A73\u7D30\u60C5\u5831\u3092\u51FA\u529B\u3059\u308B\u305F\u3081\u306E\u30D5\u30E9\u30B0\u3067\u3001\u30D0\u30F3\u30C9\u30E9\u306E\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002
+
+param.drop-in-resources-root.name=\u30EA\u30BD\u30FC\u30B9\u5185\u306E\u30C9\u30ED\u30C3\u30D7\u30FB\u30EB\u30FC\u30C8
+param.drop-in-resources-root.description=\u30EA\u30BD\u30FC\u30B9\u5185\u306E\u30D0\u30F3\u30C9\u30E9\u56FA\u6709\u306E\u30C9\u30ED\u30C3\u30D7\u3092\u63A2\u3059\u305F\u3081\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3002\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u306F\u30AF\u30E9\u30B9\u30D1\u30B9\u3092\u691C\u7D22\u3057\u307E\u3059\u3002
+
+param.secondary-launchers.name=\u30BB\u30AB\u30F3\u30C0\u30EA\u30FB\u30E9\u30F3\u30C1\u30E3
+param.secondary-launchers.description=\u30BB\u30AB\u30F3\u30C0\u30EA\u30FB\u30E9\u30F3\u30C1\u30E3\u306E\u30D0\u30F3\u30C9\u30EB\u30FB\u30D1\u30E9\u30E1\u30FC\u30BF\u60C5\u5831\u306E\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3
+
+param.file-associations.name=\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3
+param.file-associations.description=\u5404\u30DE\u30C3\u30D7\u304C\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u3092\u793A\u3059\u30DE\u30C3\u30D7\u306E\u30EA\u30B9\u30C8\u3002\u5404\u30DE\u30C3\u30D7\u3067\u4E00\u9023\u306E"fileAssociation."\u30D0\u30F3\u30C9\u30EB\u5F15\u6570\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+
+param.fa-extension.name=\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u306E\u62E1\u5F35\u5B50
+param.fa-extension.description=\u95A2\u9023\u4ED8\u3051\u308B\u30D5\u30A1\u30A4\u30EB\u62E1\u5F35\u5B50\u3001\u30C9\u30C3\u30C8\u306A\u3057\u306E\u62E1\u5F35\u5B50\u3002
+
+param.fa-content-type.name=\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u30FB\u30B3\u30F3\u30C6\u30F3\u30C4\u30FB\u30BF\u30A4\u30D7
+param.fa-content-type.description=\u95A2\u9023\u4ED8\u3051\u308B\u30B3\u30F3\u30C6\u30F3\u30C4\u30FB\u30BF\u30A4\u30D7\u3002application/x-vnd.my-awesome-app\u306A\u3069\u3067\u3059\u3002
+
+param.fa-icon.name=\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u30FB\u30A2\u30A4\u30B3\u30F3
+param.fa-icon.description=\u95A2\u9023\u4ED8\u3051\u3089\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u306B\u4F7F\u7528\u3059\u308B\u30A2\u30A4\u30B3\u30F3\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A2\u30A4\u30B3\u30F3\u3067\u3059\u3002
+
+param.fa-description.name=\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u306E\u8AAC\u660E
+param.fa-description.description=\u95A2\u9023\u4ED8\u3051\u3089\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u306B\u4F7F\u7528\u3059\u308B\u8AAC\u660E\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F"<appName>\u30D5\u30A1\u30A4\u30EB"\u3067\u3059\u3002
+
+param.commercial-features.name=\u5546\u7528\u6A5F\u80FD\u306E\u30ED\u30C3\u30AF\u89E3\u9664
+param.commercial-features.description=\u4E00\u90E8\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u306F\u5546\u7528\u6A5F\u80FD\u306E\u30ED\u30C3\u30AF\u3092\u89E3\u9664\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\u5546\u7528\u6A5F\u80FD\u306E\u30ED\u30C3\u30AF\u3092\u89E3\u9664\u3059\u308B\u306B\u306F\u3001true\u3068\u3057\u3066\u6E21\u3055\u308C\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\u305D\u3046\u3067\u306A\u3044\u5834\u5408\u306F\u7121\u8996\u3055\u308C\u307E\u3059\u3002
+
+param.com-app-cds.name=AppCDS\u306E\u6709\u52B9\u5316
+param.com-app-cds.description=\u6709\u52B9\u5316\u3055\u308C\u3001.jsa\u30D5\u30A1\u30A4\u30EB\u306E\u751F\u6210\u3092\u542B\u3080\u3001\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u5171\u6709\u3092\u542B\u3081\u3066\u30D1\u30C3\u30B1\u30FC\u30B8\u30F3\u30B0\u3057\u307E\u3059\u3002
+
+param.com-app-cds-cache-mode.name=AppCDS\u30AD\u30E3\u30C3\u30B7\u30E5\u30FB\u30E2\u30FC\u30C9
+param.com-app-cds-cache-mode.description=AppCDS .jpa\u30D5\u30A1\u30A4\u30EB\u304C\u751F\u6210\u304A\u3088\u3073\u30AD\u30E3\u30C3\u30B7\u30E5\u3055\u308C\u308B\u30E2\u30FC\u30C9\u3002\u73FE\u5728\u306E\u5024\u306F'install'\u3001'auto'\u304A\u3088\u3073'auto+install'\u3067\u3059\u3002
+
+param.com-app-cds-root.name=AppCDS\u30EB\u30FC\u30C8\u30FB\u30AF\u30E9\u30B9
+param.com-app-cds-root.description=\u30AF\u30E9\u30B9\u5171\u6709\u30C7\u30FC\u30BF\u3092\u751F\u6210\u3059\u308BAppCDS\u306E"\u30EB\u30FC\u30C8\u30FB\u30AF\u30E9\u30B9"\u306E\u30EA\u30B9\u30C8\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u3067\u3059\u3002
+
+param.source-dir.name=\u30BD\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA
+param.source-dir.description=\u30D0\u30F3\u30C9\u30EB\u3059\u308B\u30D5\u30A1\u30A4\u30EB\u3092\u542B\u3080\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3078\u306E\u30D1\u30B9\u3002
+
+param.module-path.name=\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30D1\u30B9
+param.module-path.description=Java\u30E9\u30F3\u30BF\u30A4\u30E0\u3092\u30D1\u30C3\u30B1\u30FC\u30B8\u30F3\u30B0\u3059\u308B\u969B\u306B\u3001JLink\u304C\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u63A2\u3059\u30D1\u30B9\u3067\u3059\u3002
+
+param.add-modules.name=\u8FFD\u52A0\u30E2\u30B8\u30E5\u30FC\u30EB
+param.add-modules.description=\u4F7F\u7528\u53EF\u80FD\u306A\u30B5\u30FC\u30D3\u30B9\u3092\u542B\u3080\u3001JImage\u306E\u4F5C\u6210\u306B\u8FFD\u52A0\u3059\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30EA\u30B9\u30C8\u3002
+
+param.limit-modules.name=\u5236\u9650\u30E2\u30B8\u30E5\u30FC\u30EB
+param.limit-modules.description=JImage\u306E\u4F5C\u6210\u3092\u5236\u9650\u3059\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u3002
+
+param.strip-executables.name=\u30CD\u30A4\u30C6\u30A3\u30D6\u306E\u5B9F\u884C\u53EF\u80FD\u30D5\u30A1\u30A4\u30EB\u306E\u524A\u9664
+param.strip-executables.description=JImage\u306E\u4F5C\u6210\u304B\u3089\u30CD\u30A4\u30C6\u30A3\u30D6\u306E\u5B9F\u884C\u53EF\u80FD\u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664\u3057\u307E\u3059\u3002
+
+param.main.module.name=\u30E1\u30A4\u30F3\u30FB\u30E2\u30B8\u30E5\u30FC\u30EB
+param.main.module.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30E1\u30A4\u30F3\u30FB\u30E2\u30B8\u30E5\u30FC\u30EB\u3002\u3053\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306Fmain-class\u3092\u6301\u3064\u5FC5\u8981\u304C\u3042\u308A\u3001\u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30D1\u30B9\u4E0A\u306B\u3042\u308A\u307E\u3059\u3002
+
+error.required-parameter={0}\u306F\u5FC5\u9808\u30D1\u30E9\u30E1\u30FC\u30BF\u3067\u3059\u3002
+error.no-main-class-with-main-jar=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30AF\u30E9\u30B9\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u306A\u304B\u3063\u305F\u304B\u3001jar {0}\u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F
+error.no-main-class-with-main-jar.advice=applicationClass\u3092\u6307\u5B9A\u3059\u308B\u304B\u3001jar {0}\u304C\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306EapplicationClass\u3092\u6307\u5B9A\u3057\u3066\u3044\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.no-main-class-with-classpath=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30AF\u30E9\u30B9\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u306A\u304B\u3063\u305F\u304B\u3001\u6307\u5B9A\u3055\u308C\u305F\u30AF\u30E9\u30B9\u30D1\u30B9\u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F
+error.no-main-class-with-classpath.advice=applicationClass\u3092\u6307\u5B9A\u3059\u308B\u304B\u3001\u30AF\u30E9\u30B9\u30D1\u30B9\u306B\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306EapplicationClass\u3092\u542B\u3080jar\u304C\u3042\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.no-main-class=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30AF\u30E9\u30B9\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u306A\u304B\u3063\u305F\u304B\u3001\u6307\u5B9A\u3055\u308C\u305F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30EA\u30BD\u30FC\u30B9\u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F
+error.no-main-class.advice=applicationClass\u3092\u6307\u5B9A\u3059\u308B\u304B\u3001appResources\u306B\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306EapplicationClass\u3092\u542B\u3080jar\u304C\u3042\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.main-jar-does-not-exist=\u69CB\u6210\u3055\u308C\u305F\u30E1\u30A4\u30F3jar\u306F{0}\u306B\u5B58\u5728\u3057\u307E\u305B\u3093
+error.main-jar-does-not-exist.advice=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30EA\u30BD\u30FC\u30B9\u306B\u5BFE\u3057\u3066\u76F8\u5BFE\u7684\u306B(\u7D76\u5BFE\u30D1\u30B9\u3067\u306F\u306A\u3044)\u30E1\u30A4\u30F3jar\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u3001\u305D\u306E\u30EA\u30BD\u30FC\u30B9\u5185\u306B\u5B58\u5728\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
+
+message.fx-app-does-not-match-specified-main=jar {0}\u306B\u306F\u3001\u5BA3\u8A00\u3055\u308C\u3066\u3044\u308B\u30E1\u30A4\u30F3{2}\u3068\u4E00\u81F4\u3057\u306A\u3044FX\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30AF\u30E9\u30B9{1}\u304C\u3042\u308A\u307E\u3059
+message.main-class-does-not-match-specified-main=jar {0}\u306B\u306F\u3001\u5BA3\u8A00\u3055\u308C\u3066\u3044\u308B\u30E1\u30A4\u30F3{2}\u3068\u4E00\u81F4\u3057\u306A\u3044\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9{1}\u304C\u3042\u308A\u307E\u3059
+
+warning.no.jdk.modules.found=\u8B66\u544A: JDK\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/StandardBundlerParam_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,182 @@
+param.app-name.name=\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0
+param.app-name.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u540D\u79F0\u3002
+
+param.app-fs-name.name=\u5E94\u7528\u7A0B\u5E8F\u6587\u4EF6\u7CFB\u7EDF\u540D\u79F0
+param.app-fs-name.description=\u9002\u5408\u6587\u4EF6\u7CFB\u7EDF\u4F7F\u7528\u7684\u5E94\u7528\u7A0B\u5E8F\u7684\u540D\u79F0\u3002\u901A\u5E38\u6B64\u540D\u79F0\u4EC5\u5305\u542B\u5B57\u6BCD, \u6570\u5B57, \u70B9\u548C\u77ED\u5212\u7EBF\u3002
+
+param.app-resource.description=\u8981\u653E\u5728\u8D44\u6E90\u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u3002\u5C06\u6240\u6709\u5FC5\u9700\u7684 jar \u4F5C\u4E3A\u8D44\u4EA7\u5305\u62EC\u3002
+param.app-resources.name=\u8D44\u6E90
+
+param.app-resource-list.description=RelativeFileSet \u5BF9\u8C61\u7684\u5217\u8868, \u5176\u4E2D\u5305\u542B\u8981\u653E\u5728\u8D44\u6E90\u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u3002\u5C06\u6240\u6709\u5FC5\u9700\u7684 jar \u4F5C\u4E3A\u8D44\u4EA7\u5305\u62EC\u3002
+param.app-resources-list.name=\u8D44\u6E90\u5217\u8868
+
+param.build-root.name=\u6784\u5EFA\u6839\u76EE\u5F55
+param.build-root.description=\u5728\u5176\u4E2D\u4F7F\u7528\u548C\u653E\u7F6E\u4E34\u65F6\u6587\u4EF6\u7684\u76EE\u5F55\u3002
+
+param.category.name=\u7C7B\u522B
+param.category.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u7C7B\u522B\u6216\u7EC4\u3002\u901A\u5E38\u800C\u8A00, \u8FD8\u9700\u8981\u6307\u5B9A\u5E94\u7528\u7A0B\u5E8F\u7279\u5B9A\u7C7B\u522B\u3002
+param.category.default=\u672A\u77E5
+
+param.copyright.name=\u7248\u6743
+param.copyright.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u7248\u6743\u3002
+param.copyright.default=\u7248\u6743\u6240\u6709 (C) {0,date,YYYY}
+
+param.description.name=\u8BF4\u660E
+param.description.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u66F4\u8BE6\u7EC6\u7684\u8BF4\u660E
+param.description.default=\u65E0
+
+param.desktop-shortcut-hint.name=\u5FEB\u6377\u65B9\u5F0F\u63D0\u793A
+param.desktop-shortcut-hint.description=\u5982\u679C\u6253\u5305\u7A0B\u5E8F\u53EF\u4EE5\u521B\u5EFA\u684C\u9762\u5FEB\u6377\u65B9\u5F0F, \u662F\u5426\u5E94\u521B\u5EFA?
+
+param.icon-file.name=\u56FE\u6807
+param.icon-file.description=\u5E94\u7528\u7A0B\u5E8F\u5305\u7684\u4E3B\u56FE\u6807\u3002
+
+param.identifier.name=\u6807\u8BC6\u7B26
+param.identifier.description=\u4EC0\u4E48\u662F\u6B64\u5E94\u7528\u7A0B\u5E8F\u7684\u8BA1\u7B97\u673A\u53EF\u8BFB\u6807\u8BC6\u7B26? \u683C\u5F0F\u5E94\u4E3A\u53CD\u5411\u987A\u5E8F\u7684 DNS \u540D\u79F0, \u4F8B\u5982 com.example.myapplication
+
+param.arguments.name=\u547D\u4EE4\u884C\u53C2\u6570
+param.arguments.description=\u8981\u4F20\u9012\u5230\u4E3B\u7C7B\u7684\u547D\u4EE4\u884C\u53C2\u6570 (\u542F\u52A8\u7A0B\u5E8F\u672A\u6307\u5B9A\u4EFB\u4F55\u53C2\u6570\u65F6)\u3002
+
+param.jvm-options.name=JVM \u9009\u9879
+param.jvm-options.description=\u8981\u4F20\u5165\u7684 JVM \u6807\u8BB0\u548C\u9009\u9879\u3002
+
+param.jvm-system-properties.name=JVM \u7CFB\u7EDF\u5C5E\u6027
+param.jvm-system-properties.description=JVM \u7CFB\u7EDF\u5C5E\u6027 (-Dname=value \u53D8\u4F53)\u3002
+
+param.license-file.name=\u8BB8\u53EF\u8BC1
+param.license-file.description=\u8BB8\u53EF\u8BC1\u6587\u4EF6, \u76F8\u5BF9\u4E8E\u7EC4\u5408\u7684\u5E94\u7528\u7A0B\u5E8F\u76EE\u5F55\u3002
+
+param.license-type.name=
+param.license-type.description=
+param.license-type.default=\u672A\u77E5
+
+param.main-class.name=\u4E3B\u7C7B
+param.main-class.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u4E3B\u7C7B\u3002\u53EF\u4EE5\u4E3A javafx.application.Application \u5B9E\u4F8B\u6216\u5E26\u6709 main \u65B9\u6CD5\u7684 java \u7C7B\u3002
+
+param.main-module.name=\u4E3B\u6A21\u5757
+param.main-module.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u4E3B\u6A21\u5757\u3002\u8FD9\u662F\u5305\u542B\u4E3B\u7C7B\u7684\u6A21\u5757\u3002
+
+param.classpath.name=\u4E3B Jar \u7C7B\u8DEF\u5F84
+param.classpath.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u4E3B jar \u7684\u7C7B\u8DEF\u5F84, \u76F8\u5BF9\u4E8E\u7EC4\u5408\u7684\u5E94\u7528\u7A0B\u5E8F\u76EE\u5F55\u3002
+
+param.main-jar.name=\u4E3B Jar
+param.main-jar.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u4E3B jar\u3002\u6B64 jar \u5E94\u5177\u6709\u4E3B\u7C7B, \u5E76\u4E14\u76F8\u5BF9\u4E8E\u7EC4\u5408\u7684\u5E94\u7528\u7A0B\u5E8F\u76EE\u5F55\u3002
+
+param.service-hint.name=\u670D\u52A1\u63D0\u793A
+param.service-hint.description=\u6253\u5305\u7A0B\u5E8F\u5E94\u5C06\u5E94\u7528\u7A0B\u5E8F\u6CE8\u518C\u4E3A\u670D\u52A1/\u5B88\u62A4\u7A0B\u5E8F
+
+param.start-on-install.name=\u5728\u5B89\u88C5\u65F6\u542F\u52A8
+param.start-on-install.description=\u63A7\u5236\u662F\u5426\u5E94\u5728\u5B89\u88C5\u65F6\u542F\u52A8\u670D\u52A1/\u5B88\u62A4\u7A0B\u5E8F
+
+param.stop-on-uninstall.name=\u5728\u5378\u8F7D\u65F6\u505C\u6B62
+param.stop-on-uninstall.description=\u63A7\u5236\u662F\u5426\u5E94\u5728\u5378\u8F7D\u65F6\u505C\u6B62\u670D\u52A1/\u5B88\u62A4\u7A0B\u5E8F
+
+param.run-at-startup.name=\u5728\u542F\u52A8\u65F6\u8FD0\u884C
+param.run-at-startup.description=\u63A7\u5236\u662F\u5426\u5E94\u5728\u7CFB\u7EDF\u542F\u52A8\u671F\u95F4\u542F\u52A8\u670D\u52A1/\u5B88\u62A4\u7A0B\u5E8F
+
+param.sign-bundle.name=\u5BF9\u5305\u7B7E\u540D
+param.sign-bundle.description=\u5982\u679C\u6253\u5305\u7A0B\u5E8F\u652F\u6301\u7B7E\u540D, \u5219\u8BF7\u6C42\u5BF9\u5305\u7B7E\u540D\u3002\u9ED8\u8BA4\u503C\u56E0\u6253\u5305\u7A0B\u5E8F\u800C\u5F02\u3002\u4E0D\u652F\u6301\u7B7E\u540D\u7684\u6253\u5305\u7A0B\u5E8F\u5C06\u65E0\u63D0\u793A\u5FFD\u7565\u6B64\u8BBE\u7F6E\u3002
+
+param.menu-shortcut-hint.name=\u83DC\u5355\u63D0\u793A
+param.menu-shortcut-hint.description=\u5982\u679C\u6253\u5305\u7A0B\u5E8F\u53EF\u4EE5\u5C06\u5E94\u7528\u7A0B\u5E8F\u6DFB\u52A0\u5230\u7CFB\u7EDF\u83DC\u5355, \u662F\u5426\u5E94\u6DFB\u52A0?
+
+param.name.name=\u540D\u79F0
+param.name.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u540D\u79F0\u3002
+
+param.preferences-id.name=\u9996\u9009 ID
+param.preferences-id.description=\u5728\u5176\u4E2D\u641C\u7D22\u7528\u6237 JVM \u9009\u9879\u7684\u9996\u9009\u8282\u70B9\u3002\u5176\u683C\u5F0F\u5E94\u4E3A\u4E3B\u7A0B\u5E8F\u5305\u540D\u79F0\u4EE5\u659C\u6760\u5206\u9694\u7684\u7248\u672C, \u4F8B\u5982 "com/example/myapplication"\u3002
+
+param.preloader.name=JavaFX \u9884\u52A0\u8F7D\u5668\u7C7B\u540D
+param.preloader.description=\u4EC5\u7528\u4E8E JavaFX \u5E94\u7528\u7A0B\u5E8F, \u8FD9\u662F\u9884\u52A0\u8F7D\u5668\u7C7B\u7684\u5168\u9650\u5B9A\u7C7B\u540D\u3002\u7C7B\u8DEF\u5F84\u4E2D\u5FC5\u987B\u5B58\u5728\u6B64\u7C7B, \u6700\u597D\u662F\u5728\u8DEF\u5F84\u524D\u7AEF\u3002
+
+param.runtime.name=JRE
+param.runtime.description=\u8981\u5171\u540C\u6253\u5305\u7684 Java \u8FD0\u884C\u65F6\u3002\u9ED8\u8BA4\u503C\u4E3A\u8FD0\u884C\u6253\u5305\u7A0B\u5E8F\u7684\u5F53\u524D JRE\u3002\u503C\u4E3A\u7A7A\u503C\u5C06\u5BFC\u81F4\u4E0D\u4F1A\u5171\u540C\u6253\u5305\u4EFB\u4F55 JRE, \u5E76\u4E14\u5C06\u4F7F\u7528\u7CFB\u7EDF JRE \u6765\u542F\u52A8\u5E94\u7528\u7A0B\u5E8F\u3002
+
+param.system-wide.name=\u7CFB\u7EDF\u8303\u56F4
+param.system-wide.description=\u6B64\u5E94\u7528\u7A0B\u5E8F\u662F\u5E94\u5C1D\u8BD5\u5728\u7CFB\u7EDF\u8303\u56F4\u5185\u5B89\u88C5, \u8FD8\u662F\u4EC5\u4E3A\u6BCF\u4E2A\u7528\u6237\u5B89\u88C5? \u7A7A\u503C\u8868\u793A\u4F7F\u7528\u7CFB\u7EDF\u9ED8\u8BA4\u503C\u3002
+
+param.title.name=\u6807\u9898
+param.title.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u6807\u9898\u3002
+
+param.use-javafx-packaging.name=FX \u6253\u5305
+param.use-javafx-packaging.description=\u662F\u5426\u5E94\u4F7F\u7528 JavaFX \u6253\u5305\u60EF\u4F8B?
+
+param.user-jvm-options.name=\u7528\u6237 JVM \u9009\u9879
+param.user-jvm-options.description=\u7528\u6237\u53EF\u4EE5\u8986\u76D6\u7684 JVM \u9009\u9879, \u53CA\u5176\u9ED8\u8BA4\u503C\u3002
+
+param.vendor.name=\u4F9B\u5E94\u5546
+param.vendor.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u4F9B\u5E94\u5546\u3002
+param.vendor.default=\u672A\u77E5
+
+param.version.name=\u7248\u672C
+param.version.description=\u6B64\u5E94\u7528\u7A0B\u5E8F\u7684\u7248\u672C\u3002
+param.version.default=1.0
+
+param.verbose.name=\u8BE6\u7EC6
+param.verbose.description=\u6307\u793A\u8F93\u51FA\u8BE6\u7EC6\u4FE1\u606F\u5E76\u4FDD\u5B58\u6253\u5305\u7A0B\u5E8F\u914D\u7F6E\u6587\u4EF6\u7684\u6807\u8BB0\u3002
+
+param.drop-in-resources-root.name=\u76F4\u63A5\u8BBF\u95EE\u8D44\u6E90\u6839\u76EE\u5F55
+param.drop-in-resources-root.description=\u5728\u5176\u4E2D\u67E5\u627E\u6253\u5305\u7A0B\u5E8F\u7279\u5B9A\u76F4\u63A5\u8BBF\u95EE\u8D44\u6E90\u7684\u76EE\u5F55\u3002\u5982\u679C\u672A\u8BBE\u7F6E, \u5219\u641C\u7D22\u7C7B\u8DEF\u5F84\u3002
+
+param.secondary-launchers.name=\u8F85\u52A9\u542F\u52A8\u7A0B\u5E8F
+param.secondary-launchers.description=\u8F85\u52A9\u542F\u52A8\u7A0B\u5E8F\u7684\u6253\u5305\u53C2\u6570\u4FE1\u606F\u7684\u96C6\u5408
+
+param.file-associations.name=\u6587\u4EF6\u5173\u8054
+param.file-associations.description=\u6620\u5C04\u7684\u5217\u8868, \u5176\u4E2D\u6BCF\u4E2A\u6620\u5C04\u63CF\u8FF0\u4E00\u4E2A\u6587\u4EF6\u5173\u8054\u3002\u5728\u6BCF\u4E2A\u6620\u5C04\u4E2D\u4F7F\u7528\u6253\u5305\u53C2\u6570\u7684 "fileAssociation." \u7CFB\u5217\u3002
+
+param.fa-extension.name=\u6587\u4EF6\u5173\u8054\u6269\u5C55\u540D
+param.fa-extension.description=\u8981\u5173\u8054\u7684\u6587\u4EF6\u6269\u5C55\u540D (\u4EC5\u9650\u6269\u5C55\u540D, \u4E0D\u542B\u70B9)\u3002
+
+param.fa-content-type.name=\u6587\u4EF6\u5173\u8054\u5185\u5BB9\u7C7B\u578B
+param.fa-content-type.description=\u8981\u5173\u8054\u7684\u5185\u5BB9\u7C7B\u578B\u3002\u4F8B\u5982 application/x-vnd.my-awesome-app\u3002
+
+param.fa-icon.name=\u6587\u4EF6\u5173\u8054\u56FE\u6807
+param.fa-icon.description=\u7528\u4E8E\u6240\u5173\u8054\u6587\u4EF6\u7684\u56FE\u6807\u3002\u9ED8\u8BA4\u503C\u4E3A\u5E94\u7528\u7A0B\u5E8F\u56FE\u6807\u3002
+
+param.fa-description.name=\u6587\u4EF6\u5173\u8054\u8BF4\u660E
+param.fa-description.description=\u7528\u4E8E\u6240\u5173\u8054\u6587\u4EF6\u7684\u8BF4\u660E\u3002\u9ED8\u8BA4\u503C\u4E3A "<appName> \u6587\u4EF6"\u3002
+
+param.commercial-features.name=\u5F00\u542F\u5546\u4E1A\u529F\u80FD
+param.commercial-features.description=\u4E00\u4E9B\u9009\u9879\u9700\u8981\u5F00\u542F\u5546\u4E1A\u529F\u80FD\u3002\u8FD9\u5FC5\u987B\u4F20\u5165 true \u6765\u5F00\u542F\u8FD9\u4E9B\u529F\u80FD\u3002\u5426\u5219\u5C06\u5FFD\u7565\u3002
+
+param.com-app-cds.name=\u542F\u7528 AppCDS
+param.com-app-cds.description=\u542F\u7528\u5E94\u7528\u7A0B\u5E8F\u7C7B\u6570\u636E\u5171\u4EAB\u529F\u80FD\u5E76\u6253\u5305, \u5305\u62EC\u751F\u6210 .jsa \u6587\u4EF6\u3002
+
+param.com-app-cds-cache-mode.name=AppCDS \u9AD8\u901F\u7F13\u5B58\u6A21\u5F0F
+param.com-app-cds-cache-mode.description=\u751F\u6210\u548C\u9AD8\u901F\u7F13\u5B58 AppCDS .jpa \u6587\u4EF6\u7684\u6A21\u5F0F\u3002\u5F53\u524D\u503C\u4E3A 'install', 'auto' \u548C 'auto+install'\u3002
+
+param.com-app-cds-root.name=AppCDS \u6839\u7C7B
+param.com-app-cds-root.description=\u4ECE\u5176\u4E2D\u751F\u6210\u7C7B\u5171\u4EAB\u6570\u636E\u7684 AppCDS \u7684 "\u6839\u7C7B" \u5217\u8868\u3002\u9ED8\u8BA4\u503C\u4E3A\u4E3B\u7C7B\u3002
+
+param.source-dir.name=\u6E90\u76EE\u5F55
+param.source-dir.description=\u5305\u542B\u8981\u6253\u5305\u6587\u4EF6\u7684\u76EE\u5F55\u8DEF\u5F84\u3002
+
+param.module-path.name=\u6A21\u5757\u8DEF\u5F84
+param.module-path.description=\u5728\u6253\u5305 Java \u8FD0\u884C\u65F6\u671F\u95F4, \u8FD9\u662F JLink \u5C06\u5728\u5176\u4E2D\u67E5\u627E\u6A21\u5757\u7684\u8DEF\u5F84\u3002
+
+param.add-modules.name=\u6DFB\u52A0\u6A21\u5757
+param.add-modules.description=\u8981\u6DFB\u52A0\u5230 JImage \u521B\u5EFA\u64CD\u4F5C\u7684\u6A21\u5757\u5217\u8868, \u5305\u62EC\u53EF\u80FD\u7684\u670D\u52A1\u3002
+
+param.limit-modules.name=\u9650\u5236\u6A21\u5757
+param.limit-modules.description=\u5C06 JImage \u521B\u5EFA\u64CD\u4F5C\u9650\u5236\u4E3A\u7684\u6A21\u5757\u3002
+
+param.strip-executables.name=\u5220\u9664\u672C\u673A\u53EF\u6267\u884C\u6587\u4EF6
+param.strip-executables.description=\u4ECE JImage \u521B\u5EFA\u64CD\u4F5C\u4E2D\u5220\u9664\u672C\u673A\u53EF\u6267\u884C\u6587\u4EF6\u3002
+
+param.main.module.name=\u4E3B\u6A21\u5757
+param.main.module.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u4E3B\u6A21\u5757\u3002\u6B64\u6A21\u5757\u5E94\u5177\u6709\u4E3B\u7C7B, \u5E76\u4E14\u4F4D\u4E8E\u6A21\u5757\u8DEF\u5F84\u4E0A\u3002
+
+error.required-parameter={0} \u662F\u5FC5\u9700\u7684\u53C2\u6570\u3002
+error.no-main-class-with-main-jar=\u672A\u6307\u5B9A\u5E94\u7528\u7A0B\u5E8F\u7C7B, \u5728 jar {0} \u4E2D\u4E5F\u672A\u627E\u5230\u5E94\u7528\u7A0B\u5E8F\u7C7B
+error.no-main-class-with-main-jar.advice=\u8BF7\u6307\u5B9A applicationClass \u6216\u786E\u4FDD jar {0} \u5728\u6E05\u5355\u4E2D\u6307\u5B9A\u4E00\u4E2A\u3002
+error.no-main-class-with-classpath=\u672A\u6307\u5B9A\u5E94\u7528\u7A0B\u5E8F\u7C7B, \u5728\u63D0\u4F9B\u7684\u7C7B\u8DEF\u5F84\u4E2D\u4E5F\u672A\u627E\u5230\u5E94\u7528\u7A0B\u5E8F\u7C7B
+error.no-main-class-with-classpath.advice=\u8BF7\u6307\u5B9A applicationClass \u6216\u786E\u4FDD\u7C7B\u8DEF\u5F84\u4E2D\u6709\u4E00\u4E2A jar \u5728\u6E05\u5355\u4E2D\u5305\u542B\u5B83\u3002
+error.no-main-class=\u672A\u6307\u5B9A\u5E94\u7528\u7A0B\u5E8F\u7C7B, \u5728\u63D0\u4F9B\u7684\u5E94\u7528\u7A0B\u5E8F\u8D44\u6E90\u4E2D\u4E5F\u672A\u627E\u5230\u5E94\u7528\u7A0B\u5E8F\u7C7B
+error.no-main-class.advice=\u8BF7\u6307\u5B9A applicationClass \u6216\u786E\u4FDD appResources \u4E2D\u6709\u4E00\u4E2A jar \u5728\u6E05\u5355\u4E2D\u5305\u542B\u5B83\u3002
+error.main-jar-does-not-exist=\u914D\u7F6E\u7684\u4E3B jar \u4E0D\u5B58\u5728 {0}
+error.main-jar-does-not-exist.advice=\u4E3B jar \u5FC5\u987B\u76F8\u5BF9\u4E8E\u5E94\u7528\u7A0B\u5E8F\u8D44\u6E90\u6307\u5B9A (\u4E0D\u662F\u7EDD\u5BF9\u8DEF\u5F84), \u5E76\u4E14\u5FC5\u987B\u5B58\u5728\u4E8E\u8FD9\u4E9B\u8D44\u6E90\u4E2D\u3002
+
+message.fx-app-does-not-match-specified-main=jar {0} \u5177\u6709\u4E0E\u6240\u58F0\u660E\u4E3B {2} \u4E0D\u5339\u914D\u7684 FX \u5E94\u7528\u7A0B\u5E8F\u7C7B {1}
+message.main-class-does-not-match-specified-main=jar {0} \u5177\u6709\u4E0E\u6240\u58F0\u660E\u4E3B {2} \u4E0D\u5339\u914D\u7684\u4E3B\u7C7B {1}
+
+warning.no.jdk.modules.found=\u8B66\u544A: \u672A\u627E\u5230 JDK \u6A21\u5757\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/builders/AbstractAppImageBuilder.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,5 @@
+message.using-default-resource=Using default package resource {0} (add {1} to the class path to customize)
+message.using-custom-resource-from-file=Using custom package resource {0} (loaded from file {1})
+message.using-custom-resource-from-classpath=Using custom package resource {0} (loaded from {1})
+message.using-default-resource-from-classpath=Using default package resource {0} (add {1} to the class path to customize)
+message.jvm-user-arg-is-null=WARNING\: a jvmuserarg has a null name or value.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/builders/AbstractAppImageBuilder_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,5 @@
+message.using-default-resource=\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528({1}\u3092\u30AF\u30E9\u30B9\u30FB\u30D1\u30B9\u306B\u8FFD\u52A0\u3057\u3066\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA)
+message.using-custom-resource-from-file=\u30AB\u30B9\u30BF\u30E0\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528(\u30D5\u30A1\u30A4\u30EB{1}\u304B\u3089\u30ED\u30FC\u30C9\u6E08)
+message.using-custom-resource-from-classpath=\u30AB\u30B9\u30BF\u30E0\u30FB\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528({1}\u304B\u3089\u30ED\u30FC\u30C9\u6E08)
+message.using-default-resource-from-classpath=\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30BD\u30FC\u30B9{0}\u306E\u4F7F\u7528({1}\u3092\u30AF\u30E9\u30B9\u30FB\u30D1\u30B9\u306B\u8FFD\u52A0\u3057\u3066\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA)
+message.jvm-user-arg-is-null=\u8B66\u544A: jvmuserarg\u306Bnull\u306E\u540D\u524D\u307E\u305F\u306F\u5024\u304C\u3042\u308A\u307E\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/builders/AbstractAppImageBuilder_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,5 @@
+message.using-default-resource=\u4F7F\u7528\u9ED8\u8BA4\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u5C06 {1} \u6DFB\u52A0\u5230\u7C7B\u8DEF\u5F84\u4EE5\u5B9A\u5236)
+message.using-custom-resource-from-file=\u4F7F\u7528\u5B9A\u5236\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u4ECE\u6587\u4EF6 {1} \u52A0\u8F7D)
+message.using-custom-resource-from-classpath=\u4F7F\u7528\u5B9A\u5236\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u4ECE {1} \u52A0\u8F7D)
+message.using-default-resource-from-classpath=\u4F7F\u7528\u9ED8\u8BA4\u7A0B\u5E8F\u5305\u8D44\u6E90 {0} (\u5C06 {1} \u6DFB\u52A0\u5230\u7C7B\u8DEF\u5F84\u4EE5\u5B9A\u5236)
+message.jvm-user-arg-is-null=\u8B66\u544A: jvmuserarg \u7684\u540D\u79F0\u6216\u503C\u4E3A\u7A7A\u503C\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/jre.list	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,49 @@
+; This file contains a list of all modules in a modular JDK that match a JRE.
+
+java.base
+java.compiler
+java.datatransfer
+java.xml
+java.prefs
+java.desktop
+java.instrument
+java.logging
+java.management
+java.security.sasl
+java.naming
+java.rmi
+java.management.rmi
+java.net.http
+java.scripting
+java.security.jgss
+java.transaction.xa
+java.sql
+java.sql.rowset
+java.xml.crypto
+java.smartcardio
+jdk.accessibility
+jdk.charsets
+jdk.crypto.ec
+jdk.crypto.cryptoki
+jdk.dynalink
+jdk.httpserver
+jdk.management
+jdk.unsupported
+jdk.jdeps
+jdk.jdwp.agent
+jdk.jlink
+jdk.jsobject
+jdk.localedata
+jdk.management.agent
+jdk.naming.dns
+jdk.naming.rmi
+jdk.net
+jdk.packager
+jdk.packager.services
+jdk.scripting.nashorn
+jdk.scripting.nashorn.shell
+jdk.sctp
+jdk.security.auth
+jdk.security.jgss
+jdk.xml.dom
+jdk.zipfs
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/jdk/packager/internal/resources/server.jre.list	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,56 @@
+; This file contains a list of all modules in a modular JDK that match a JRE.
+
+java.base
+java.compiler
+java.datatransfer
+java.xml
+java.prefs
+java.desktop
+java.instrument
+java.logging
+java.management
+java.security.sasl
+java.naming
+java.rmi
+java.management.rmi
+java.net.http
+java.scripting
+java.security.jgss
+java.transaction.xa
+java.sql
+java.sql.rowset
+java.xml.crypto
+java.se
+java.smartcardio
+jdk.internal.jvmstat
+jdk.attach
+jdk.charsets
+jdk.compiler
+jdk.crypto.ec
+jdk.crypto.cryptoki
+jdk.dynalink
+jdk.httpserver
+jdk.internal.le
+jdk.internal.opt
+jdk.internal.vm.ci
+jdk.management
+jdk.unsupported
+jdk.internal.vm.compiler
+jdk.internal.vm.compiler.management
+jdk.jartool
+jdk.jcmd
+jdk.jdwp.agent
+jdk.jdi
+jdk.jsobject
+jdk.jstatd
+jdk.localedata
+jdk.management.agent
+jdk.naming.dns
+jdk.naming.rmi
+jdk.net
+jdk.scripting.nashorn
+jdk.sctp
+jdk.security.auth
+jdk.security.jgss
+jdk.xml.dom
+jdk.zipfs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/classes/module-info.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * Defines the Java packager tool, jpackager.
+ *
+ * <p>The jpackager is a tool for generating bundles for self-contained applications.
+ * It can be located under the name {@code "jpackager"} using the {@link ToolProvider}, for example:
+ * <pre>{@code
+ * ToolProvider jpackager = ToolProvider.findFirst("jpackager").orElseThrow(...);
+ * jpackager.run(...);
+ * }</pre>
+ *
+ * @moduleGraph
+ * @since 11
+ */
+
+module jdk.packager {
+    requires jdk.jlink;
+
+    requires java.xml;
+    requires java.logging;
+    requires java.desktop;
+
+    uses jdk.packager.internal.Bundler;
+    uses jdk.packager.internal.Bundlers;
+
+    provides jdk.packager.internal.Bundlers with
+        jdk.packager.internal.BasicBundlers;
+
+    provides java.util.spi.ToolProvider
+        with jdk.packager.internal.JavaPackagerToolProvider;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/Exports.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+#include "Package.h"
+#include "PlatformString.h"
+#include "PropertyFile.h"
+#include "Lock.h"
+#include "Java.h"
+
+#include "jni.h"
+
+
+class UserJVMArgsExports {
+private:
+    // This is not a class to create an instance of.
+    UserJVMArgsExports();
+
+    static jobjectArray MapKeysToJObjectArray(JNIEnv *env, OrderedMap<TString, TString> map) {
+        std::vector<TString> keys = map.GetKeys();
+        JavaStringArray result(env, keys.size());
+
+        for (unsigned int index = 0; index < keys.size(); index++) {
+            PlatformString value(keys[index]);
+            try {
+                result.SetValue(index, value.toJString(env));
+            }
+            catch (const JavaException&) {}
+        }
+        return result.GetData();
+    }
+
+public:
+    static jstring _getUserJvmOptionDefaultValue(JNIEnv *env, jstring option) {
+        if (env == NULL || option == NULL)
+            return NULL;
+
+        jstring result = NULL;
+
+        Package& package = Package::GetInstance();
+        OrderedMap<TString, TString> defaultuserargs = package.GetDefaultJVMUserArgs();
+        TString loption = PlatformString(env, option).toString();
+
+        TString temp;
+        defaultuserargs.GetValue(loption, temp);
+        PlatformString value = temp;
+        try {
+            result = value.toJString(env);
+        }
+        catch (const JavaException&) {
+        }
+
+        return result;
+    }
+
+    static jobjectArray _getUserJvmOptionDefaultKeys(JNIEnv *env) {
+        if (env == NULL)
+            return NULL;
+
+        jobjectArray result = NULL;
+
+        Package& package = Package::GetInstance();
+
+        try {
+            result = MapKeysToJObjectArray(env, package.GetDefaultJVMUserArgs());
+        }
+        catch (const JavaException&) {
+        }
+
+        return result;
+    }
+
+    static jstring _getUserJvmOptionValue(JNIEnv *env, jstring option) {
+        if (env == NULL || option == NULL)
+            return NULL;
+
+        jstring result = NULL;
+
+        Package& package = Package::GetInstance();
+        OrderedMap<TString, TString> userargs = package.GetJVMUserArgs();
+
+        try {
+            TString loption = PlatformString(env, option).toString();
+            TString temp;
+            userargs.GetValue(loption, temp);
+            PlatformString value = temp;
+            result = value.toJString(env);
+        }
+        catch (const JavaException&) {
+        }
+
+        return result;
+    }
+
+    static void _setUserJvmKeysAndValues(JNIEnv *env, jobjectArray options, jobjectArray values) {
+        if (env == NULL || options == NULL || values == NULL)
+            return;
+
+        Package& package = Package::GetInstance();
+        OrderedMap<TString, TString> newMap;
+
+        try {
+            JavaStringArray loptions(env, options);
+            JavaStringArray lvalues(env, values);
+
+            for (unsigned int index = 0; index < loptions.Count(); index++) {
+                TString name = PlatformString(env, loptions.GetValue(index)).toString();
+                TString value = PlatformString(env, lvalues.GetValue(index)).toString();
+                newMap.Append(name, value);
+            }
+        }
+        catch (const JavaException&) {
+            return;
+        }
+
+        package.SetJVMUserArgOverrides(newMap);
+    }
+
+    static jobjectArray _getUserJvmOptionKeys(JNIEnv *env) {
+        if (env == NULL)
+            return NULL;
+
+        jobjectArray result = NULL;
+
+        Package& package = Package::GetInstance();
+
+        try {
+            result = MapKeysToJObjectArray(env, package.GetJVMUserArgs());
+        }
+        catch (const JavaException&) {
+        }
+
+        return result;
+    }
+};
+
+
+extern "C" {
+    JNIEXPORT jstring JNICALL Java_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions__1getUserJvmOptionDefaultValue(JNIEnv *env, jclass klass, jstring option) {
+        return UserJVMArgsExports::_getUserJvmOptionDefaultValue(env, option);
+    }
+
+    JNIEXPORT jobjectArray JNICALL Java_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions__1getUserJvmOptionDefaultKeys(JNIEnv *env, jclass klass) {
+        return UserJVMArgsExports::_getUserJvmOptionDefaultKeys(env);
+    }
+
+    JNIEXPORT jstring JNICALL Java_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions__1getUserJvmOptionValue(JNIEnv *env, jclass klass, jstring option) {
+        return UserJVMArgsExports::_getUserJvmOptionValue(env, option);
+    }
+
+    JNIEXPORT void JNICALL Java_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions__1setUserJvmKeysAndValues(JNIEnv *env, jclass klass, jobjectArray options, jobjectArray values) {
+        UserJVMArgsExports::_setUserJvmKeysAndValues(env, options, values);
+    }
+
+    JNIEXPORT jobjectArray JNICALL Java_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions__1getUserJvmOptionKeys(JNIEnv *env, jclass klass) {
+        return UserJVMArgsExports::_getUserJvmOptionKeys(env);
+    }
+}
+
+#ifdef DEBUG
+// Build with debug info. Create a class:
+//
+// package com;
+//
+// class DebugExports {
+//   static {
+//      System.loadLibrary("packager");
+//   }
+//
+//   public static native boolean isdebugged();
+//
+//   public static native int getpid();
+// }
+//
+// Use the following in Java in the main or somewhere else:
+//
+// import com.DebugExports;
+// import java.util.Arrays;
+//
+// if (Arrays.asList(args).contains("-debug")) {
+//   System.out.println("pid=" + getpid());
+//
+//   while (true) {
+//     if (isdebugged() == true) {
+//       break;
+//     }
+//   }
+// }
+//
+// The call to isdebugger() will wait until a native debugger is attached. The process
+// identifier (pid) will be printed to the console for you to attach your debugger to.
+extern "C" {
+    JNIEXPORT jboolean JNICALL Java_com_DebugExports_isdebugged(JNIEnv *env, jclass klass) {
+        jboolean result = false;
+        Package& package = Package::GetInstance();
+
+        if (package.Debugging() == dsNative) {
+            Platform& platform = Platform::GetInstance();
+            result = platform.GetDebugState() != dsNone;
+        }
+
+        return result;
+    }
+
+    JNIEXPORT jint JNICALL Java_com_DebugExports_getpid(JNIEnv *env, jclass klass) {
+        Platform& platform = Platform::GetInstance();
+        return platform.GetProcessID();
+    }
+}
+#endif //DEBUG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/Exports.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class jdk_packager_services_userjvmoptions_LauncherUserJvmOptions */
+
+#ifndef _Included_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions
+#define _Included_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     jdk_packager_services_userjvmoptions_LauncherUserJvmOptions
+ * Method:    _getUserJvmOptionDefaultValue
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions__1getUserJvmOptionDefaultValue
+  (JNIEnv *, jclass, jstring);
+
+/*
+ * Class:     jdk_packager_services_userjvmoptions_LauncherUserJvmOptions
+ * Method:    _getUserJvmOptionDefaultKeys
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions__1getUserJvmOptionDefaultKeys
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     jdk_packager_services_userjvmoptions_LauncherUserJvmOptions
+ * Method:    _getUserJvmOptionValue
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions__1getUserJvmOptionValue
+  (JNIEnv *, jclass, jstring);
+
+/*
+ * Class:     jdk_packager_services_userjvmoptions_LauncherUserJvmOptions
+ * Method:    _setUserJvmKeysAndValues
+ * Signature: ([Ljava/lang/String;[Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions__1setUserJvmKeysAndValues
+  (JNIEnv *, jclass, jobjectArray, jobjectArray);
+
+/*
+ * Class:     jdk_packager_services_userjvmoptions_LauncherUserJvmOptions
+ * Method:    _getUserJvmOptionKeys
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_jdk_packager_services_userjvmoptions_LauncherUserJvmOptions__1getUserJvmOptionKeys
+  (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/FilePath.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,695 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "FilePath.h"
+
+#include <algorithm>
+#include <list>
+
+#ifdef WINDOWS
+#include <ShellAPI.h>
+#endif //WINDOWS
+
+#ifdef POSIX
+#include <sys/stat.h>
+#endif //POSIX
+
+
+bool FilePath::FileExists(const TString FileName) {
+    bool result = false;
+#ifdef WINDOWS
+    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);
+    }
+#endif //WINDOWS
+#ifdef POSIX
+    struct stat buf;
+
+    if ((stat(StringToFileSystemString(FileName), &buf) == 0) && (S_ISREG(buf.st_mode) != 0)) {
+        result = true;
+    }
+#endif //POSIX
+    return result;
+}
+
+bool FilePath::DirectoryExists(const TString DirectoryName) {
+    bool result = false;
+#ifdef WINDOWS
+    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);
+    }
+#endif //WINDOWS
+#ifdef POSIX
+    struct stat buf;
+
+    if ((stat(StringToFileSystemString(DirectoryName), &buf) == 0) && (S_ISDIR(buf.st_mode) != 0)) {
+        result = true;
+    }
+#endif //POSIX
+    return result;
+}
+
+#ifdef WINDOWS
+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;
+}
+#endif //WINDOWS
+
+bool FilePath::DeleteFile(const TString FileName) {
+    bool result = false;
+
+    if (FileExists(FileName) == true) {
+#ifdef WINDOWS
+        TString lFileName = FixPathForPlatform(FileName);
+        FileAttributes attributes(lFileName);
+
+        if (attributes.Contains(faReadOnly) == true) {
+            attributes.Remove(faReadOnly);
+        }
+
+        result = ::DeleteFile(lFileName.data()) == TRUE;
+#endif //WINDOWS
+#ifdef POSIX
+        if (unlink(StringToFileSystemString(FileName)) == 0) {
+            result = true;
+        }
+#endif //POSIX
+    }
+
+    return result;
+}
+
+bool FilePath::DeleteDirectory(const TString DirectoryName) {
+    bool result = false;
+
+    if (DirectoryExists(DirectoryName) == true) {
+#ifdef WINDOWS
+        SHFILEOPSTRUCTW fos = {0};
+        TString directoryName = FixPathForPlatform(DirectoryName);
+        DynamicBuffer<TCHAR> lDirectoryName(directoryName.size() + 2);
+        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;
+#endif //WINDOWS
+#ifdef POSIX
+        if (unlink(StringToFileSystemString(DirectoryName)) == 0) {
+            result = true;
+        }
+#endif //POSIX
+    }
+
+    return result;
+}
+
+TString FilePath::IncludeTrailingSeparater(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::IncludeTrailingSeparater(const char* value) {
+    TString lvalue = PlatformString(value).toString();
+    return IncludeTrailingSeparater(lvalue);
+}
+
+TString FilePath::IncludeTrailingSeparater(const wchar_t* value) {
+    TString lvalue = PlatformString(value).toString();
+    return IncludeTrailingSeparater(lvalue);
+}
+
+TString FilePath::ExtractFilePath(TString Path) {
+#ifdef WINDOWS
+    TString result;
+    size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
+    if (slash != TString::npos)
+        result = Path.substr(0, slash);
+    return result;
+#endif //WINDOWS
+#ifdef POSIX
+    return dirname(StringToFileSystemString(Path));
+#endif //POSIX
+}
+
+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) {
+#ifdef WINDOWS
+    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;
+#endif // WINDOWS
+#ifdef POSIX
+    return basename(StringToFileSystemString(Path));
+#endif //POSIX
+}
+
+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);
+#ifdef WINDOWS
+    // 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;
+        }
+    }
+#endif // WINDOWS
+    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;
+
+#ifdef WINDOWS
+        if (_wmkdir(lpath.data()) == 0) {
+#endif // WINDOWS
+#ifdef POSIX
+        mode_t mode = S_IRWXU;
+        if (!ownerOnly) {
+            mode |= S_IRWXG | S_IROTH | S_IXOTH;
+        }
+        if (mkdir(StringToFileSystemString(lpath), mode) == 0) {
+#endif //POSIX
+            result = true;
+        }
+        else {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+void FilePath::ChangePermissions(TString FileName, bool ownerOnly) {
+#ifdef POSIX
+    mode_t mode = S_IRWXU;
+    if (!ownerOnly) {
+        mode |= S_IRWXG | S_IROTH | S_IXOTH;
+    }
+    chmod(FileName.data(), mode);
+#endif // POSIX
+}
+
+//--------------------------------------------------------------------------------------------------
+
+#include <algorithm>
+
+FileAttributes::FileAttributes(const TString FileName, bool FollowLink) {
+    FFileName = FileName;
+    FFollowLink = FollowLink;
+    ReadAttributes();
+}
+
+bool FileAttributes::WriteAttributes() {
+    bool result = false;
+
+#ifdef WINDOWS
+    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 faIntegrityStream: {
+//                attributes = attributes & FILE_ATTRIBUTE_INTEGRITY_STREAM;
+//                break;
+//            }
+            case faNormal: {
+                attributes = attributes & FILE_ATTRIBUTE_NORMAL;
+                break;
+            }
+            case faNotContentIndexed: {
+                attributes = attributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
+                break;
+            }
+//            case faNoScrubData: {
+//                attributes = attributes & FILE_ATTRIBUTE_NO_SCRUB_DATA;
+//                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;
+    }
+#endif // WINDOWS
+#ifdef POSIX
+    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;
+    }
+#endif //POSIX
+
+    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;
+
+#ifdef WINDOWS
+    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_INTEGRITY_STREAM) { FAttributes.push_back(faIntegrityStream); }
+        if (attributes | FILE_ATTRIBUTE_NORMAL) { FAttributes.push_back(faNormal); }
+        if (attributes | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) { FAttributes.push_back(faNotContentIndexed); }
+        //if (attributes | FILE_ATTRIBUTE_NO_SCRUB_DATA) { FAttributes.push_back(faNoScrubData); }
+        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); }
+    }
+#endif // WINDOWS
+#ifdef POSIX
+    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);
+        }
+    }
+#endif //POSIX
+
+    return result;
+}
+
+bool FileAttributes::Valid(const FileAttribute Value) {
+    bool result = false;
+
+    switch (Value) {
+#ifdef WINDOWS
+        case faHidden:
+#endif // WINDOWS
+#ifdef POSIX
+        case faReadWrite:
+        case faWriteOnly:
+        case faExecute:
+
+        case faGroupReadWrite:
+        case faGroupWriteOnly:
+        case faGroupReadOnly:
+        case faGroupExecute:
+
+        case faOthersReadWrite:
+        case faOthersWriteOnly:
+        case faOthersReadOnly:
+        case faOthersExecute:
+#endif //POSIX
+
+        case faReadOnly: {
+            result = true;
+            break;
+        }
+        default:
+            break;
+    }
+
+    return result;
+}
+
+void FileAttributes::Append(FileAttribute Value) {
+    if (Valid(Value) == true) {
+#ifdef POSIX
+        if ((Value == faReadOnly && Contains(faWriteOnly) == true) ||
+            (Value == faWriteOnly && Contains(faReadOnly) == true)) {
+            Value = faReadWrite;
+        }
+#endif //POSIX
+
+        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) {
+#ifdef POSIX
+        if (Value == faReadOnly && Contains(faReadWrite) == true) {
+            Append(faWriteOnly);
+            Remove(faReadWrite);
+        }
+        else if (Value == faWriteOnly && Contains(faReadWrite) == true) {
+            Append(faReadOnly);
+            Remove(faReadWrite);
+        }
+#endif //POSIX
+
+        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.packager/share/native/library/common/FilePath.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#ifndef FILEPATH_H
+#define FILEPATH_H
+
+#include "Platform.h"
+#include "PlatformString.h"
+
+#include <vector>
+
+enum FileAttribute {
+#ifdef WINDOWS
+    faArchive = FILE_ATTRIBUTE_ARCHIVE,
+    faCompressed = FILE_ATTRIBUTE_COMPRESSED,
+    faDevice = FILE_ATTRIBUTE_DEVICE,
+    faDirectory = FILE_ATTRIBUTE_DIRECTORY,
+    faEncrypted = FILE_ATTRIBUTE_ENCRYPTED,
+    faHidden = FILE_ATTRIBUTE_HIDDEN,
+    //faIntegrityStream = FILE_ATTRIBUTE_INTEGRITY_STREAM,
+    faNormal = FILE_ATTRIBUTE_NORMAL,
+    faNotContentIndexed = FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
+    //faNoScrubData = FILE_ATTRIBUTE_NO_SCRUB_DATA,
+    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 //WINDOWS  
+#ifdef POSIX
+    faBlockSpecial,
+    faCharacterSpecial,
+    faFIFOSpecial,
+    faNormal,
+    faDirectory,
+    faSymbolicLink,
+    faSocket,
+
+    // Owner
+    faReadOnly,
+    faWriteOnly,
+    faReadWrite,
+    faExecute,
+
+    // Group
+    faGroupReadOnly,
+    faGroupWriteOnly,
+    faGroupReadWrite,
+    faGroupExecute,
+
+    // Others
+    faOthersReadOnly,
+    faOthersWriteOnly,
+    faOthersReadWrite,
+    faOthersExecute,
+
+    faHidden
+#endif //POSIX
+};
+
+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 IncludeTrailingSeparater(const TString value);
+    static TString IncludeTrailingSeparater(const char* value);
+    static TString IncludeTrailingSeparater(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.packager/share/native/library/common/GenericPlatform.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "GenericPlatform.h"
+
+#include <fstream>
+#include <locale>
+
+#ifdef WINDOWS
+#include <codecvt>
+#endif //WINDOWS
+
+
+GenericPlatform::GenericPlatform(void) {
+}
+
+GenericPlatform::~GenericPlatform(void) {
+}
+
+TString GenericPlatform::GetConfigFileName() {
+    TString result;
+    TString basedir = GetPackageAppDirectory();
+
+    if (basedir.empty() == false) {
+        basedir = FilePath::IncludeTrailingSeparater(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;
+}
+
+TString GenericPlatform::GetPackageAppDirectory() {
+#if defined(WINDOWS) || defined(LINUX)
+    return FilePath::IncludeTrailingSeparater(GetPackageRootDirectory()) + _T("app");
+#endif //WINDOWS || LINUX
+#ifdef MAC
+    return FilePath::IncludeTrailingSeparater(GetPackageRootDirectory()) + _T("Java");
+#endif
+}
+
+TString GenericPlatform::GetPackageLauncherDirectory() {
+#if defined(WINDOWS) || defined(LINUX)
+    return GetPackageRootDirectory();
+#endif //WINDOWS || LINUX
+#ifdef MAC
+    return FilePath::IncludeTrailingSeparater(GetPackageRootDirectory()) + _T("MacOS");
+#endif
+}
+
+std::list<TString> GenericPlatform::LoadFromFile(TString FileName) {
+    std::list<TString> result;
+
+    if (FilePath::FileExists(FileName) == true) {
+        std::wifstream stream(FileName.data());
+
+#ifdef WINDOWS
+        const std::locale empty_locale = std::locale::empty();
+#endif //WINDOWS
+#ifdef POSIX
+        const std::locale empty_locale = std::locale::classic();
+#endif //POSIX
+#if defined(WINDOWS)
+        const std::locale utf8_locale = std::locale(empty_locale, new std::codecvt_utf8<wchar_t>());
+        stream.imbue(utf8_locale);
+#endif //WINDOWS
+
+        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 GenericPlatform::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());
+
+    FilePath::ChangePermissions(FileName.data(), ownerOnly);
+
+#ifdef WINDOWS
+    const std::locale empty_locale = std::locale::empty();
+#endif //WINDOWS
+#ifdef POSIX
+    const std::locale empty_locale = std::locale::classic();
+#endif //POSIX
+#if defined(WINDOWS)
+    const std::locale utf8_locale = std::locale(empty_locale, new std::codecvt_utf8<wchar_t>());
+    stream.imbue(utf8_locale);
+#endif //WINDOWS || MAC
+
+    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;
+        }
+    }
+}
+
+#if defined(WINDOWS) || defined(LINUX)
+TString GenericPlatform::GetAppName() {
+    TString result = GetModuleFileName();
+    result = FilePath::ExtractFileName(result);
+#if defined(WINDOWS)
+    result = FilePath::ChangeFileExt(result, _T(""));
+#endif
+    return result;
+}
+#endif //WINDOWS || LINUX
+
+std::map<TString, TString> GenericPlatform::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(CONFIG_APP_ID_KEY,        _T("app.preferences.id")));
+    keys.insert(std::map<TString, TString>::value_type(JVM_RUNTIME_KEY,          _T("app.runtime")));
+    keys.insert(std::map<TString, TString>::value_type(PACKAGER_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_JVMOPTIONS,     _T("JVMOptions")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_JVMUSEROPTIONS, _T("JVMUserOptions")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS, _T("JVMUserOverrideOptions")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_APPCDSJVMOPTIONS, _T("AppCDSJVMOptions")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_APPCDSGENERATECACHEJVMOPTIONS, _T("AppCDSGenerateCacheJVMOptions")));
+    keys.insert(std::map<TString, TString>::value_type(CONFIG_SECTION_ARGOPTIONS,     _T("ArgOptions")));
+
+    return keys;
+}
+
+#ifdef DEBUG
+DebugState GenericPlatform::GetDebugState() {
+    DebugState result = dsNone;
+
+    if (IsNativeDebuggerPresent() == true) {
+        result = dsNative;
+    }
+
+    return result;
+}
+#endif //DEBUG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/GenericPlatform.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#ifndef GENERICPLATFORM_H
+#define GENERICPLATFORM_H
+
+#include "FilePath.h"
+//#include "Platform.h"
+
+#ifdef WINDOWS
+#pragma warning( push )
+#pragma warning( disable : 4250 ) // C4250 - 'class1' : inherits 'class2::member' via dominance
+#endif
+
+class GenericPlatform : virtual public Platform {
+public:
+    GenericPlatform(void);
+    virtual ~GenericPlatform(void);
+
+    virtual TString GetPackageAppDirectory();
+    virtual TString GetPackageLauncherDirectory();
+
+    virtual TString GetConfigFileName();
+
+    virtual std::list<TString> LoadFromFile(TString FileName);
+    virtual void SaveToFile(TString FileName, std::list<TString> Contents, bool ownerOnly);
+
+#if defined(WINDOWS) || defined(LINUX)
+    virtual TString GetAppName();
+#endif //WINDOWS || LINUX
+
+    virtual std::map<TString, TString> GetKeys();
+
+#ifdef DEBUG
+    virtual DebugState GetDebugState();
+#endif //DEBUG
+};
+#ifdef WINDOWS
+#pragma warning( pop ) // C4250
+#endif
+#endif //GENERICPLATFORM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/Helpers.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Helpers.h"
+#include "PlatformString.h"
+#include "PropertyFile.h"
+
+
+bool Helpers::SplitOptionIntoNameValue(TString option, TString& Name, TString& Value) {
+    bool result = false;
+    Name = _T("");
+    Value = _T("");
+    unsigned int index = 0;
+
+    for (; index < option.length(); index++) {
+        TCHAR c = option[index];
+
+        switch (c) {
+            case '=': {
+                index++;
+                result = 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 (result) {
+        Value = option.substr(index, index - option.length());
+    }
+
+    return true;
+}
+
+
+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::GetJVMArgsFromConfig(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;
+            Helpers::SplitOptionIntoNameValue(argvalue, name, value);
+            result.Append(name, value);
+        }
+    }
+
+    return result;
+}
+
+OrderedMap<TString, TString> Helpers::GetJVMUserArgsFromConfig(IPropertyContainer* config) {
+    OrderedMap<TString, TString> result;
+
+    for (unsigned int index = 0; index < config->GetCount(); index++) {
+        TString prefix = TString(_T("jvmuserarg.")) + PlatformString(index + 1).toString();
+        TString argname = prefix + _T(".name");
+        TString argvalue = prefix + _T(".value");
+        TString name;
+        TString value;
+
+        if ((config->GetValue(argname, name) == false) || (config->GetValue(argvalue, value) == false)) {
+            break;
+        }
+        else if ((name.empty() == false) && (value.empty() == false)) {
+            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;
+}
+
+void AppendToIni(PropertyFile &Source, IniFile* Destination, TString Key) {
+    TString value;
+
+    if (Source.GetValue(Key, value) == true) {
+        Platform& platform = Platform::GetInstance();
+        std::map<TString, TString> keys = platform.GetKeys();
+        Destination->Append(keys[CONFIG_SECTION_APPLICATION], Key, value);
+    }
+}
+
+void Helpers::LoadOldConfigFile(TString FileName, IniFile* Container) {
+    PropertyFile propertyFile;
+
+    if (propertyFile.LoadFromFile(FileName) == true) {
+        Platform& platform = Platform::GetInstance();
+
+        std::map<TString, TString> keys = platform.GetKeys();
+
+        // Application Section
+        AppendToIni(propertyFile, Container, keys[CONFIG_MAINJAR_KEY]);
+        AppendToIni(propertyFile, Container, keys[CONFIG_MAINMODULE_KEY]);
+        AppendToIni(propertyFile, Container, keys[CONFIG_MAINCLASSNAME_KEY]);
+        AppendToIni(propertyFile, Container, keys[CONFIG_CLASSPATH_KEY]);
+        AppendToIni(propertyFile, Container, keys[APP_NAME_KEY]);
+        AppendToIni(propertyFile, Container, keys[CONFIG_APP_ID_KEY]);
+        AppendToIni(propertyFile, Container, keys[JVM_RUNTIME_KEY]);
+        AppendToIni(propertyFile, Container, keys[PACKAGER_APP_DATA_DIR]);
+
+        AppendToIni(propertyFile, Container, keys[CONFIG_APP_MEMORY]);
+        AppendToIni(propertyFile, Container, keys[CONFIG_SPLASH_KEY]);
+
+        // JVMOptions Section
+        OrderedMap<TString, TString> JVMArgs = Helpers::GetJVMArgsFromConfig(&propertyFile);
+        Container->AppendSection(keys[CONFIG_SECTION_JVMOPTIONS], JVMArgs);
+
+        // JVMUserOptions Section
+        OrderedMap<TString, TString> defaultJVMUserArgs = Helpers::GetJVMUserArgsFromConfig(&propertyFile);
+        Container->AppendSection(keys[CONFIG_SECTION_JVMUSEROPTIONS], defaultJVMUserArgs);
+
+        // ArgOptions Section
+        std::list<TString> args = Helpers::GetArgsFromConfig(&propertyFile);
+        OrderedMap<TString, TString> convertedArgs;
+
+        for (std::list<TString>::iterator iterator = args.begin(); iterator != args.end(); iterator++) {
+            TString arg = *iterator;
+            TString name;
+            TString value;
+
+            if (Helpers::SplitOptionIntoNameValue(arg, name, value) == true) {
+                convertedArgs.Append(name, value);
+            }
+        }
+
+        Container->AppendSection(keys[CONFIG_SECTION_ARGOPTIONS], convertedArgs);
+    }
+}
+
+void Helpers::LoadOldUserConfigFile(TString FileName, IniFile* Container) {
+    PropertyFile propertyFile;
+    Container = NULL;
+
+    if (propertyFile.LoadFromFile(FileName) == true) {
+        Container = new IniFile();
+        Platform& platform = Platform::GetInstance();
+
+        std::map<TString, TString> keys = platform.GetKeys();
+
+        // JVMUserOverridesOptions Section
+        OrderedMap<TString, TString> defaultJVMUserArgs = Helpers::GetJVMUserArgsFromConfig(&propertyFile);
+        Container->AppendSection(keys[CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS], defaultJVMUserArgs);
+    }
+}
+
+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++) {
+       pair<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];
+
+//        Environment::NewLine;
+
+        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.packager/share/native/library/common/Helpers.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#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> GetJVMArgsFromConfig(IPropertyContainer* config);
+    static OrderedMap<TString, TString> GetJVMUserArgsFromConfig(IPropertyContainer* config);
+    //static OrderedMap<TString, TString> GetConfigFromJVMUserArgs(OrderedMap<TString, TString> Value);
+    static std::list<TString> GetArgsFromConfig(IPropertyContainer* config);
+
+    static void LoadOldConfigFile(TString FileName, IniFile* Container);
+    static void LoadOldUserConfigFile(TString FileName, IniFile* Container);
+
+    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.packager/share/native/library/common/IniFile.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#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++) {
+        pair<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;
+
+        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.packager/share/native/library/common/IniFile.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#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.packager/share/native/library/common/Java.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Java.h"
+#include "PlatformString.h"
+
+#include <list>
+
+
+//--------------------------------------------------------------------------------------------------
+
+#ifdef DEBUG
+TString JavaException::CreateExceptionMessage(JNIEnv* Env, jthrowable Exception,
+    jmethodID GetCauseMethod, jmethodID GetStackTraceMethod, jmethodID ThrowableToTStringMethod,
+    jmethodID FrameToTStringMethod) {
+
+    TString result;
+    jobjectArray frames = (jobjectArray)Env->CallObjectMethod(Exception, GetStackTraceMethod);
+
+    // Append Throwable.toTString().
+    if (0 != frames) {
+        jstring jstr = (jstring)Env->CallObjectMethod(Exception, ThrowableToTStringMethod);
+        const char* str = Env->GetStringUTFChars(jstr, 0);
+        result += PlatformString(str).toPlatformString();
+        Env->ReleaseStringUTFChars(jstr, str);
+        Env->DeleteLocalRef(jstr);
+    }
+
+    // Append stack trace if one exists.
+    if (Env->GetArrayLength(frames) > 0) {
+        jsize i = 0;
+
+        for (i = 0; i < Env->GetArrayLength(frames); i++) {
+            // Get the string from the next frame and append it to
+            // the error message.
+            jobject frame = Env->GetObjectArrayElement(frames, i);
+            jstring obj = (jstring)Env->CallObjectMethod(frame, FrameToTStringMethod);
+            const char* str = Env->GetStringUTFChars(obj, 0);
+            result += _T("\n  ");
+            result += PlatformString(str).toPlatformString();
+            Env->ReleaseStringUTFChars(obj, str);
+            Env->DeleteLocalRef(obj);
+            Env->DeleteLocalRef(frame);
+        }
+    }
+
+    // If Exception has a cause then append the stack trace messages.
+    if (0 != frames) {
+        jthrowable cause = (jthrowable)Env->CallObjectMethod(Exception, GetCauseMethod);
+
+        if (cause != NULL) {
+            result += CreateExceptionMessage(Env, cause, GetCauseMethod,
+                GetStackTraceMethod, ThrowableToTStringMethod,
+                FrameToTStringMethod);
+        }
+    }
+
+    return result;
+}
+#endif //DEBUG
+
+JavaException::JavaException() : Exception() {}
+
+//#ifdef WINDOWS
+JavaException::JavaException(JNIEnv *Env, const TString Message) : Exception(Message) {
+//#endif //WINDOWS
+//#ifdef POSIX
+//JavaException::JavaException(JNIEnv *Env, TString message) {
+//#endif //POSIX
+
+    FEnv = Env;
+    FException = Env->ExceptionOccurred();
+    Env->ExceptionClear();
+
+#ifdef DEBUG
+    Platform& platform = Platform::GetInstance();
+
+    if (platform.GetDebugState() == dsNone) {
+        jclass ThrowableClass = Env->FindClass("java/lang/Throwable");
+
+        if (FEnv->ExceptionCheck() == JNI_TRUE) {
+            Env->ExceptionClear();
+            return;
+        }
+
+        jmethodID GetCauseMethod = Env->GetMethodID(ThrowableClass,
+                                                    "getCause",
+                                                    "()Ljava/lang/Throwable;");
+
+        if (FEnv->ExceptionCheck() == JNI_TRUE) {
+            Env->ExceptionClear();
+            return;
+        }
+
+        jmethodID GetStackTraceMethod = Env->GetMethodID(ThrowableClass,
+                                                            "getStackTrace",
+                                                            "()[Ljava/lang/StackTraceElement;");
+
+        if (FEnv->ExceptionCheck() == JNI_TRUE) {
+            Env->ExceptionClear();
+            return;
+        }
+
+        jmethodID ThrowableToTStringMethod = Env->GetMethodID(ThrowableClass,
+                                                                "toString",
+                                                                "()Ljava/lang/String;");
+
+        if (FEnv->ExceptionCheck() == JNI_TRUE) {
+            Env->ExceptionClear();
+            return;
+        }
+
+        jclass FrameClass = Env->FindClass("java/lang/StackTraceElement");
+
+        if (FEnv->ExceptionCheck() == JNI_TRUE) {
+            Env->ExceptionClear();
+            return;
+        }
+
+        jmethodID FrameToTStringMethod = Env->GetMethodID(FrameClass,
+                                                            "toString",
+                                                            "()Ljava/lang/String;");
+
+        if (FEnv->ExceptionCheck() == JNI_TRUE) {
+            Env->ExceptionClear();
+            return;
+        }
+
+        TString lmessage = CreateExceptionMessage(Env, FException, GetCauseMethod,
+            GetStackTraceMethod, ThrowableToTStringMethod, FrameToTStringMethod);
+        SetMessage(lmessage);
+    }
+#endif //DEBUG
+}
+
+void JavaException::Rethrow() {
+    FEnv->Throw(FException);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+JavaStaticMethod::JavaStaticMethod(JNIEnv *Env, jclass Class, jmethodID Method) {
+    FEnv = Env;
+    FClass = Class;
+    FMethod = Method;
+}
+
+void JavaStaticMethod::CallVoidMethod(int Count, ...) {
+    va_list args;
+    va_start(args, Count);
+    FEnv->CallStaticVoidMethodV(FClass, FMethod, args);
+    va_end(args);
+
+    if (FEnv->ExceptionCheck() == JNI_TRUE) {
+        Messages& messages = Messages::GetInstance();
+        throw JavaException(FEnv, messages.GetMessage(ERROR_INVOKING_METHOD));
+    }
+}
+
+JavaStaticMethod::operator jmethodID () {
+    return FMethod;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+JavaMethod::JavaMethod(JNIEnv *Env, jobject Obj, jmethodID Method) {
+    FEnv = Env;
+    FObj = Obj;
+    FMethod = Method;
+}
+
+void JavaMethod::CallVoidMethod(int Count, ...) {
+    va_list args;
+    va_start(args, Count);
+    FEnv->CallVoidMethodV(FObj, FMethod, args);
+    va_end(args);
+
+    if (FEnv->ExceptionCheck() == JNI_TRUE) {
+        Messages& messages = Messages::GetInstance();
+        throw JavaException(FEnv, messages.GetMessage(ERROR_INVOKING_METHOD));
+    }
+}
+
+JavaMethod::operator jmethodID () {
+    return FMethod;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+JavaClass::JavaClass(JNIEnv *Env, TString Name) {
+    FEnv = Env;
+    FClassName = Name;
+    FClass = FEnv->FindClass(PlatformString(FClassName));
+
+    if (FClass == NULL || FEnv->ExceptionCheck() == JNI_TRUE) {
+        Messages& messages = Messages::GetInstance();
+        TString message = messages.GetMessage(CLASS_NOT_FOUND);
+        message = PlatformString::Format(message, FClassName.data());
+        throw JavaException(FEnv, message);
+    }
+}
+
+JavaClass::~JavaClass() {
+    FEnv->DeleteLocalRef(FClass);
+
+    if (FEnv->ExceptionCheck() == JNI_TRUE) {
+        // throw JavaException(FEnv, _T("Error"));  // VS2017 - FIXME
+    }
+}
+
+JavaStaticMethod JavaClass::GetStaticMethod(TString Name, TString Signature) {
+    jmethodID method = FEnv->GetStaticMethodID(FClass, PlatformString(Name), PlatformString(Signature));
+
+    if (method == NULL || FEnv->ExceptionCheck() == JNI_TRUE) {
+        Messages& messages = Messages::GetInstance();
+        TString message = messages.GetMessage(METHOD_NOT_FOUND);
+        message = PlatformString::Format(message, Name.data(), FClassName.data());
+        throw JavaException(FEnv, message);
+    }
+
+    return JavaStaticMethod(FEnv, FClass, method);
+}
+
+JavaClass::operator jclass () {
+    return FClass;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+void JavaStringArray::Initialize(size_t Size) {
+    JavaClass jstringClass(FEnv, _T("java/lang/String"));
+
+    if (FEnv->ExceptionCheck() == JNI_TRUE) {
+        Messages& messages = Messages::GetInstance();
+        TString message = messages.GetMessage(CLASS_NOT_FOUND);
+        message = PlatformString::Format(message, _T("String"));
+        throw JavaException(FEnv, message.data());
+    }
+
+    jstring str = PlatformString("").toJString(FEnv);
+    FData = (jobjectArray)FEnv->NewObjectArray((jsize)Size, jstringClass, str);
+
+    if (FEnv->ExceptionCheck() == JNI_TRUE) {
+        throw JavaException(FEnv, _T("Error"));
+    }
+}
+
+JavaStringArray::JavaStringArray(JNIEnv *Env, size_t Size) {
+    FEnv = Env;
+    Initialize(Size);
+}
+
+JavaStringArray::JavaStringArray(JNIEnv *Env, jobjectArray Data) {
+    FEnv = Env;
+    FData = Data;
+}
+
+JavaStringArray::JavaStringArray(JNIEnv *Env, std::list<TString> Items) {
+    FEnv = Env;
+    Initialize(Items.size());
+    unsigned int index = 0;
+
+    for (std::list<TString>::const_iterator iterator = Items.begin(); iterator != Items.end(); iterator++) {
+        TString item = *iterator;
+        SetValue(index, PlatformString(item).toJString(FEnv));
+        index++;
+    }
+}
+
+jobjectArray JavaStringArray::GetData() {
+    return FData;
+}
+
+void JavaStringArray::SetValue(jsize Index, jstring Item) {
+    FEnv->SetObjectArrayElement(FData, Index, Item);
+
+    if (FEnv->ExceptionCheck() == JNI_TRUE) {
+        throw JavaException(FEnv, _T("Error"));
+    }
+}
+
+jstring JavaStringArray::GetValue(jsize Index) {
+    jstring result = (jstring)FEnv->GetObjectArrayElement(FData, Index);
+
+    if (FEnv->ExceptionCheck() == JNI_TRUE) {
+        throw JavaException(FEnv, _T("Error"));
+    }
+
+    return result;
+}
+
+unsigned int JavaStringArray::Count() {
+    unsigned int result = FEnv->GetArrayLength(FData);
+
+    if (FEnv->ExceptionCheck() == JNI_TRUE) {
+        throw JavaException(FEnv, _T("Error"));
+    }
+
+    return result;
+}
+
+//--------------------------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/Java.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#ifndef JAVA_H
+#define JAVA_H
+
+#include "Platform.h"
+#include "Messages.h"
+
+#include "jni.h"
+
+
+class JavaClass;
+class JavaStaticMethod;
+class JavaMethod;
+class JavaStringArray;
+
+
+class JavaException : public Exception {
+// Prohibit Heap-Based Classes.
+private:
+    static void *operator new(size_t size);
+
+private:
+#ifdef DEBUG
+    static TString CreateExceptionMessage(JNIEnv* Env, jthrowable Exception,
+        jmethodID GetCauseMethod, jmethodID GetStackTraceMethod, jmethodID ThrowableToStringMethod,
+        jmethodID FrameToStringMethod);
+#endif //DEBUG
+
+    jthrowable FException;
+    JNIEnv *FEnv;
+
+public:
+    explicit JavaException();
+    explicit JavaException(JNIEnv *Env, const TString message);
+    virtual ~JavaException() throw() {}
+
+    void Rethrow();
+};
+
+
+class JavaStaticMethod {
+// Prohibit Heap-Based Classes.
+private:
+    static void *operator new(size_t size);
+    static void operator delete(void *ptr);
+
+private:
+    JNIEnv *FEnv;
+    jmethodID FMethod;
+    jclass FClass;
+public:
+    JavaStaticMethod(JNIEnv *Env, jclass Class, jmethodID Method);
+
+    void CallVoidMethod(int Count, ...);
+    operator jmethodID ();
+};
+
+
+class JavaMethod {
+// Prohibit Heap-Based Classes.
+private:
+    static void *operator new(size_t size);
+    static void operator delete(void *ptr);
+
+    JavaMethod(JavaMethod const&); // Don't Implement.
+    void operator=(JavaMethod const&); // Don't implement
+
+private:
+    JNIEnv *FEnv;
+    jmethodID FMethod;
+    jobject FObj;
+public:
+    JavaMethod(JNIEnv *Env, jobject Obj, jmethodID Method);
+
+    void CallVoidMethod(int Count, ...);
+    operator jmethodID ();
+};
+
+
+class JavaClass {
+// Prohibit Heap-Based Classes.
+private:
+    static void *operator new(size_t size);
+    static void operator delete(void *ptr);
+
+    JavaClass(JavaClass const&); // Don't Implement.
+    void operator=(JavaClass const&); // Don't implement
+
+private:
+    JNIEnv *FEnv;
+    jclass FClass;
+    TString FClassName;
+
+public:
+    JavaClass(JNIEnv *Env, TString Name);
+    ~JavaClass();
+
+    JavaStaticMethod GetStaticMethod(TString Name, TString Signature);
+    operator jclass ();
+};
+
+
+class JavaStringArray {
+// Prohibit Heap-Based Classes.
+private:
+    static void *operator new(size_t size);
+    static void operator delete(void *ptr);
+
+    JavaStringArray(JavaStringArray const&); // Don't Implement.
+    void operator=(JavaStringArray const&); // Don't implement
+
+private:
+    JNIEnv *FEnv;
+    jobjectArray FData;
+
+    void Initialize(size_t Size);
+
+public:
+    JavaStringArray(JNIEnv *Env, size_t Size);
+    JavaStringArray(JNIEnv *Env, jobjectArray Data);
+    JavaStringArray(JNIEnv *Env, std::list<TString> Array);
+
+    jobjectArray GetData();
+    void SetValue(jsize Index, jstring Item);
+    jstring GetValue(jsize Index);
+    unsigned int Count();
+};
+
+#endif //JAVA_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/JavaUserPreferences.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "JavaUserPreferences.h"
+#include "Lock.h"
+
+#include "WindowsPlatform.h"
+#include "LinuxPlatform.h"
+#include "MacPlatform.h"
+
+
+JavaUserPreferences::JavaUserPreferences(void) {
+}
+
+JavaUserPreferences* JavaUserPreferences::CreateInstance(void) {
+    JavaUserPreferences* result;
+#ifdef WINDOWS
+    result = new WindowsJavaUserPreferences();
+#endif // WINDOWS
+#ifdef LINUX
+    result = new LinuxJavaUserPreferences();
+#endif // LINUX
+#ifdef MAC
+    result = new MacJavaUserPreferences();
+#endif // MAC
+    return result;
+}
+
+JavaUserPreferences::~JavaUserPreferences(void){
+}
+
+OrderedMap<TString, TString> JavaUserPreferences::GetData() {
+    return FMap;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/JavaUserPreferences.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#ifndef JAVAUSERPREFERENCES_H
+#define JAVAUSERPREFERENCES_H
+
+
+#include "Helpers.h"
+
+#include <map>
+
+
+class JavaUserPreferences {
+protected:
+    TString FAppid;
+    OrderedMap<TString, TString> FMap;
+
+public:
+    static JavaUserPreferences* CreateInstance(void);
+    JavaUserPreferences(void);
+    virtual ~JavaUserPreferences(void);
+
+    OrderedMap<TString, TString> GetData();
+
+public:
+    virtual bool Load(TString Appid) = 0;
+};
+
+#endif //JAVAUSERPREFERENCES_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/JavaVirtualMachine.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "JavaVirtualMachine.h"
+#include "Platform.h"
+#include "PlatformString.h"
+#include "FilePath.h"
+#include "Package.h"
+#include "Java.h"
+#include "Helpers.h"
+#include "Messages.h"
+#include "Macros.h"
+#include "PlatformThread.h"
+
+#include "jni.h"
+
+#include <map>
+#include <list>
+#include <sstream>
+
+
+bool RunVM(JvmLaunchType type) {
+    bool result = false;
+    JavaVirtualMachine javavm;
+
+    switch (type){
+        case USER_APP_LAUNCH:
+            result = javavm.StartJVM();
+            break;
+        case SINGLE_INSTANCE_NOTIFICATION_LAUNCH:
+            result = javavm.NotifySingleInstance();
+            break;
+        default:
+            break;
+    }
+
+    if (!result) {
+        Platform& platform = Platform::GetInstance();
+        platform.ShowMessage(_T("Failed to launch JVM\n"));
+    }
+
+    return result;
+}
+
+JavaLibrary::JavaLibrary() : Library(), FCreateProc(NULL)  {
+}
+
+bool JavaLibrary::JavaVMCreate(size_t argc, char *argv[]) {
+    if (FCreateProc == NULL) {
+        FCreateProc = (JVM_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;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+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) {
+    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();
+}
+
+// jvmuserargs can have a trailing equals in the key. This needs to be removed to use
+// other parts of the launcher.
+OrderedMap<TString, TString> RemoveTrailingEquals(OrderedMap<TString, TString> Map) {
+    OrderedMap<TString, TString> result;
+
+    std::vector<TString> keys = Map.GetKeys();
+
+    for (size_t index = 0; index < keys.size(); index++) {
+        TString name = keys[index];
+        TString value;
+
+        if (Map.GetValue(name, value) == true) {
+            // If the last character of the key is an equals, then remove it. If there is no
+            // equals then combine the two as a key.
+            TString::iterator i = name.end();
+            i--;
+
+            if (*i == '=') {
+                name = name.substr(0, name.size() - 1);
+            }
+            else {
+                i = value.begin();
+
+                if (*i == '=') {
+                    value = value.substr(1, value.size() - 1);
+                }
+                else {
+                    name = name + value;
+                    value = _T("");
+                }
+            }
+
+            result.Append(name, value);
+        }
+    }
+
+    return result;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+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.AppendValue(_T("-Dapp.preferences.id"), package.GetAppID());
+    options.AppendValues(package.GetJVMArgs());
+    options.AppendValues(RemoveTrailingEquals(package.GetJVMUserArgs()));
+
+#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, false);
+}
+
+bool JavaVirtualMachine::NotifySingleInstance() {
+    Package& package = Package::GetInstance();
+
+    std::list<TString> vmargs;
+    vmargs.push_back(package.GetCommandName());
+
+    JavaOptions options;
+    options.AppendValue(_T("-Djava.library.path"), package.GetPackageAppDirectory()
+                      + FilePath::PathSeparator() + package.GetPackageLauncherDirectory());
+    options.AppendValue(_T("-Djava.launcher.path"), package.GetPackageLauncherDirectory());
+    // launch SingleInstanceNewActivation.main() to pass arguments to another instance
+    options.AppendValue(_T("-m"));
+    options.AppendValue(_T("jdk.packager.services/jdk.packager.services.singleton.SingleInstanceNewActivation"));
+
+    configureLibrary();
+
+    return launchVM(options, vmargs, true);
+}
+
+void JavaVirtualMachine::configureLibrary() {
+    Platform& platform = Platform::GetInstance();
+    Package& package = Package::GetInstance();
+    // TODO: Clean this up. Because of bug JDK-8131321 the opening of the PE file
+    // fails in WindowsPlatform.cpp on the check to
+    // if (pNTHeader->Signature == IMAGE_NT_SIGNATURE)
+    TString libName = package.GetJVMLibraryFileName();
+#ifdef _WIN64
+    if (FilePath::FileExists(_T("msvcr100.dll")) == true) {
+        javaLibrary.AddDependency(_T("msvcr100.dll"));
+    }
+#else
+    javaLibrary.AddDependencies(
+        platform.FilterOutRuntimeDependenciesForPlatform(platform.GetLibraryImports(libName)));
+#endif
+    javaLibrary.Load(libName);
+}
+
+bool JavaVirtualMachine::launchVM(JavaOptions& options, std::list<TString>& vmargs, bool addSiProcessId) {
+    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
+
+    if (addSiProcessId) {
+        // add single instance process ID as a first argument
+        TProcessID pid = platform.GetSingleInstanceProcessId();
+        std::ostringstream s;
+        s << pid;
+        std::string procIdStr(s.str());
+        vmargs.push_back(TString(procIdStr.begin(), procIdStr.end()));
+    }
+
+    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);
+    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.packager/share/native/library/common/JavaVirtualMachine.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#ifndef JAVAVIRTUALMACHINE_H
+#define JAVAVIRTUALMACHINE_H
+
+
+#include "jni.h"
+#include "Platform.h"
+
+
+enum JvmLaunchType {
+    USER_APP_LAUNCH,
+    SINGLE_INSTANCE_NOTIFICATION_LAUNCH,
+    JVM_LAUNCH_TYPES_NUM
+};
+
+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();
+};
+
+// Private typedef for function pointer casting
+#define LAUNCH_FUNC "JLI_Launch"
+
+typedef int (JNICALL *JVM_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 JavaLibrary : public Library {
+    JVM_CREATE FCreateProc;
+    JavaLibrary(const TString &FileName);
+public:
+    JavaLibrary();
+    bool JavaVMCreate(size_t argc, char *argv[]);
+};
+
+class JavaVirtualMachine {
+private:
+    JavaLibrary javaLibrary;
+
+    void configureLibrary();
+    bool launchVM(JavaOptions& options, std::list<TString>& vmargs, bool addSiProcessId);
+public:
+    JavaVirtualMachine();
+    ~JavaVirtualMachine(void);
+
+    bool StartJVM();
+    bool NotifySingleInstance();
+};
+
+bool RunVM(JvmLaunchType type);
+
+#endif //JAVAVIRTUALMACHINE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/LinuxPlatform.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,1227 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+
+#ifdef LINUX
+
+#include "JavaVirtualMachine.h"
+#include "LinuxPlatform.h"
+#include "PlatformString.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>
+
+#define LINUX_PACKAGER_TMP_DIR "/.java/packager/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(), GenericPlatform(), PosixPlatform() {
+    FMainThread = pthread_self();
+}
+
+LinuxPlatform::~LinuxPlatform(void) {
+}
+
+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 ((len = readlink("/proc/self/exe", buffer.GetData(), MAX_PATH - 1)) != -1) {
+        buffer[len] = '\0';
+        result = buffer.GetData();
+    }
+
+    return result;
+}
+
+void LinuxPlatform::SetCurrentDirectory(TString Value) {
+    chdir(PlatformString(Value).toPlatformString());
+}
+
+TString LinuxPlatform::GetPackageRootDirectory() {
+    TString filename = GetModuleFileName();
+    return FilePath::ExtractFilePath(filename);
+}
+
+TString LinuxPlatform::GetAppDataDirectory() {
+    TString result;
+    TString home = GetEnv(_T("HOME"));
+
+    if (home.empty() == false) {
+        result += FilePath::IncludeTrailingSeparater(home) + _T(".local");
+    }
+
+    return result;
+}
+
+ISectionalPropertyContainer* LinuxPlatform::GetConfigFile(TString FileName) {
+    IniFile *result = new IniFile();
+
+    if (result->LoadFromFile(FileName) == false) {
+        // New property file format was not found, attempt to load old property file format.
+        Helpers::LoadOldConfigFile(FileName, result);
+    }
+
+    return result;
+}
+
+TString LinuxPlatform::GetBundledJVMLibraryFileName(TString RuntimePath) {
+    TString result = FilePath::IncludeTrailingSeparater(RuntimePath) +
+        "lib/jli/libjli.so";
+
+    if (FilePath::FileExists(result) == false) {
+        result = FilePath::IncludeTrailingSeparater(RuntimePath) +
+            "lib/jli/libjli.so";
+    }
+
+    return result;
+}
+
+bool LinuxPlatform::IsMainThread() {
+    bool result = (FMainThread == pthread_self());
+    return result;
+}
+
+TString LinuxPlatform::getTmpDirString() {
+    return TString(LINUX_PACKAGER_TMP_DIR);
+}
+
+void LinuxPlatform::reactivateAnotherInstance() {
+    if (singleInstanceProcessId == 0) {
+        printf("Unable to reactivate another instance, PID is undefined");
+        return;
+    }
+
+    const ProcessReactivator reactivator(singleInstanceProcessId);
+}
+
+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;
+}
+
+#ifdef DEBUG
+bool LinuxPlatform::IsNativeDebuggerPresent() {
+    // gdb opens file descriptors stdin=3, stdout=4, stderr=5 whereas
+    // a typical prog uses only stdin=0, stdout=1, stderr=2.
+    bool result = false;
+    FILE *fd = fopen("/tmp", "r");
+
+    if (fileno(fd) > 5) {
+        result = true;
+    }
+
+    fclose(fd);
+    return result;
+}
+
+int LinuxPlatform::GetProcessID() {
+    int pid = getpid();
+    return pid;
+}
+#endif //DEBUG
+
+//--------------------------------------------------------------------------------------------------
+
+#ifndef __UNIX_DEPLOY_PLATFORM__
+#define __UNIX_DEPLOY_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 DEPLOY_MULTIBYTE_SNPRINTF snprintf
+
+#define DEPLOY_SNPRINTF(buffer, sizeOfBuffer, count, format, ...) \
+    snprintf((buffer), (count), (format), __VA_ARGS__)
+
+#define DEPLOY_PRINTF(format, ...) \
+    printf((format), ##__VA_ARGS__)
+
+#define DEPLOY_FPRINTF(dest, format, ...) \
+    fprintf((dest), (format), __VA_ARGS__)
+
+#define DEPLOY_SSCANF(buf, format, ...) \
+    sscanf((buf), (format), __VA_ARGS__)
+
+#define DEPLOY_STRDUP(strSource) \
+    strdup((strSource))
+
+//return "error code" (like on Windows)
+static int DEPLOY_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;
+}
+
+static int DEPLOY_STRNCAT(char *strDest, size_t numberOfElements, const char *strSource, size_t count) {
+    // strncat always return null terminated string
+    char *s = strncat(strDest, strSource, count);
+    return (s == strDest) ? 0 : 1;
+}
+
+#define DEPLOY_STRICMP(x, y) \
+    strcasecmp((x), (y))
+
+#define DEPLOY_STRNICMP(x, y, cnt) \
+    strncasecmp((x), (y), (cnt))
+
+#define DEPLOY_STRNCMP(x, y, cnt) \
+    strncmp((x), (y), (cnt))
+
+#define DEPLOY_STRLEN(x) \
+    strlen((x))
+
+#define DEPLOY_STRSTR(x, y) \
+    strstr((x), (y))
+
+#define DEPLOY_STRCHR(x, y) \
+    strchr((x), (y))
+
+#define DEPLOY_STRRCHR(x, y) \
+    strrchr((x), (y))
+
+#define DEPLOY_STRPBRK(x, y) \
+    strpbrk((x), (y))
+
+#define DEPLOY_GETENV(x) \
+    getenv((x))
+
+#define DEPLOY_PUTENV(x) \
+    putenv((x))
+
+#define DEPLOY_STRCMP(x, y) \
+    strcmp((x), (y))
+
+#define DEPLOY_STRCPY(x, y) \
+    strcpy((x), (y))
+
+#define DEPLOY_STRCAT(x, y) \
+    strcat((x), (y))
+
+#define DEPLOY_ATOI(x) \
+    atoi((x))
+
+static int getFileSize(TCHAR* filename) {
+    struct stat statBuf;
+    if (stat(filename, &statBuf) == 0) {
+        return statBuf.st_size;
+    }
+    return -1;
+}
+
+#define DEPLOY_FILE_SIZE(filename) getFileSize(filename)
+
+#define DEPLOY_FOPEN(x, y) \
+    fopen((x), (y))
+
+#define DEPLOY_FGETS(x, y, z) \
+    fgets((x), (y), (z))
+
+#define DEPLOY_REMOVE(x) \
+    remove((x))
+
+#define DEPLOY_SPAWNV(mode, cmd, args) \
+    spawnv((mode), (cmd), (args))
+
+#define DEPLOY_ISDIGIT(ch) isdigit(ch)
+
+// for non-unicode, just return the input string for
+// the following 2 conversions
+#define DEPLOY_NEW_MULTIBYTE(message) message
+
+#define DEPLOY_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 DEPLOY_RELEASE_MULTIBYTE(tmpMBCS)
+
+#define DEPLOY_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 DEPLOY_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 (DEPLOY_STRNCMP(p, _T("<!--"), 4) == 0) {
+            SKIP_CHARS(p, 4);
+            do {
+                if (DEPLOY_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 (DEPLOY_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 (DEPLOY_STRNCMP(p, _T("<?"), 2) == 0) {
+            SKIP_CHARS(p, 2);
+            do {
+                if (DEPLOY_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 (DEPLOY_STRNCMP(p, _T("&amp;"), 5) == 0) {
+            *q++ = '&';
+            SKIP_CHARS(p, 5);
+        } else if (DEPLOY_STRNCMP(p, _T("&lt;"), 4)  == 0) {
+            *q = '<';
+            SKIP_CHARS(p, 4);
+        } else if (DEPLOY_STRNCMP(p, _T("&gt;"), 4)  == 0) {
+            *q = '>';
+            SKIP_CHARS(p, 4);
+        } else if (DEPLOY_STRNCMP(p, _T("&apos;"), 6)  == 0) {
+            *q = '\'';
+            SKIP_CHARS(p, 6);
+        } else if (DEPLOY_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;
+    DEPLOY_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, DEPLOY_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();
+
+        /* Skip until '>', '/>' or EOF. This should really be an error, */
+        /* but we are loose */
+//        if(CurTokenType == TOKEN_EMPTY_CLOSE_BRACKET ||
+//               CurTokenType == TOKEN_CLOSE_BRACKET ||
+//               CurTokenType  == TOKEN_EOF) {
+//            println("XML Parsing error: wrong kind of token found");
+//            return NULL;
+//        }
+
+        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, DEPLOY_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 = DEPLOY_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, DEPLOY_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 && DEPLOY_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 (DEPLOY_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) {
+     DEPLOY_PRINTF(_T("\n"));
+     indent(indt);
+     DEPLOY_PRINTF(_T("<%s"), node->_name);
+     PrintXMLAttributes(node->_attributes);
+     if (node->_sub == NULL) {
+       DEPLOY_PRINTF(_T("/>\n"));
+     } else {
+       DEPLOY_PRINTF(_T(">"));
+       PrintXMLDocument(node->_sub, indt + 1);
+       indent(indt);
+       DEPLOY_PRINTF(_T("</%s>"), node->_name);
+     }
+  } else {
+    DEPLOY_PRINTF(_T("%s"), node->_name);
+  }
+  PrintXMLDocument(node->_next, indt);
+}
+
+static void PrintXMLAttributes(XMLAttribute* attr) {
+  if (attr == NULL) return;
+
+  DEPLOY_PRINTF(_T(" %s=\"%s\""), attr->_name, attr->_value);
+  PrintXMLAttributes(attr->_next);
+}
+
+static void indent(int indt) {
+    int i;
+    for(i = 0; i < indt; i++) {
+        DEPLOY_PRINTF(_T("  "));
+    }
+}
+
+const TCHAR *CDStart = _T("<![CDATA[");
+const TCHAR *CDEnd = _T("]]>");
+
+
+static TCHAR* SkipPCData(TCHAR *p) {
+    TCHAR *end = DEPLOY_STRSTR(p, CDEnd);
+    if (end != NULL) {
+        return end+sizeof(CDEnd);
+    }
+    return (++p);
+}
+
+static int IsPCData(TCHAR *p) {
+    const int size = sizeof(CDStart);
+    return (DEPLOY_STRNCMP(CDStart, p, size) == 0);
+}
+
+//--------------------------------------------------------------------------------------------------
+
+LinuxJavaUserPreferences::LinuxJavaUserPreferences(void) : JavaUserPreferences() {
+}
+
+LinuxJavaUserPreferences::~LinuxJavaUserPreferences(void) {
+}
+
+TString LinuxJavaUserPreferences::GetUserPrefFileName(TString Appid) {
+    TString result;
+    struct passwd *pw = getpwuid(getuid());
+    TString homedir = pw->pw_dir;
+    TString userOverrideFileName = FilePath::IncludeTrailingSeparater(homedir) +
+        FilePath::IncludeTrailingSeparater(_T(".java/.userPrefs")) +
+        FilePath::IncludeTrailingSeparater(Appid) +
+        _T("JVMUserOptions/prefs.xml");
+
+    if (FilePath::FileExists(userOverrideFileName) == true) {
+        result = userOverrideFileName;
+    }
+
+    return result;
+}
+
+OrderedMap<TString, TString> ReadNode(XMLNode* node) {
+    OrderedMap<TString, TString> result;
+    XMLNode* keyNode = FindXMLChild(node->_sub, _T("entry"));
+
+    while (keyNode != NULL) {
+        TString key = FindXMLAttribute(keyNode->_attributes, _T("key"));
+        TString value = FindXMLAttribute(keyNode->_attributes, _T("value"));
+        keyNode = keyNode->_next;
+
+        if (key.empty() == false) {
+            result.Append(key, value);
+        }
+    }
+
+    return result;
+}
+
+OrderedMap<TString, TString> GetJvmUserArgs(TString filename) {
+    OrderedMap<TString, TString> result;
+
+    if (FilePath::FileExists(filename) == true) {
+        //scan file for the key
+        FILE* fp = fopen(PlatformString(filename).toPlatformString(), "r");
+
+        if (fp != NULL) {
+            fseek(fp, 0, SEEK_END);
+            long fsize = ftell(fp);
+            rewind(fp);
+            DynamicBuffer<char> buffer(fsize + 1);
+            fread(buffer.GetData(), fsize, 1, fp);
+            fclose(fp);
+            buffer[fsize] = 0;
+
+            XMLNode* node = NULL;
+            XMLNode* doc = ParseXMLDocument(buffer.GetData());
+
+            if (doc != NULL) {
+                node = FindXMLChild(doc, _T("map"));
+
+                if (node != NULL) {
+                    result = ReadNode(node);
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+bool LinuxJavaUserPreferences::Load(TString Appid) {
+    bool result = false;
+    TString filename = GetUserPrefFileName(Appid);
+
+    if (FilePath::FileExists(filename) == true) {
+        FMap = GetJvmUserArgs(filename);
+        result = true;
+    }
+
+    return result;
+}
+
+namespace {
+template<class funcType>
+class DllFunction {
+    const Library& lib;
+    funcType funcPtr;
+    std::string theName;
+
+public:
+    DllFunction(const Library& library, const std::string &funcName): lib(library) {
+        funcPtr = reinterpret_cast<funcType>(lib.GetProcAddress(funcName));
+        if (!funcPtr) {
+            throw std::runtime_error("Failed to load function \"" + funcName + "\" from \"" + library.GetName() + "\" library");
+        }
+    }
+
+    operator funcType() const {
+        return funcPtr;
+    }
+};
+} // namespace
+
+extern "C" {
+typedef Status (*XInitThreadsFuncPtr)();
+typedef Display* (*XOpenDisplayFuncPtr)(char *display_name);
+
+typedef Atom (*XInternAtomFuncPtr)(Display *display, char *atom_name, Bool only_if_exists);
+
+typedef Window (*XDefaultRootWindowFuncPtr)(Display *display);
+
+typedef int (*XCloseDisplayFuncPtr)(Display *display);
+}
+
+ProcessReactivator::ProcessReactivator(pid_t pid): _pid(pid) {
+    const std::string libname = "libX11.so";
+    if(!libX11.Load(libname)) {
+        throw std::runtime_error("Failed to load \"" + libname + "\" library");
+    }
+
+    DllFunction<XInitThreadsFuncPtr> XInitThreadsFunc(libX11, "XInitThreads");
+
+    XInitThreadsFunc();
+
+    DllFunction<XOpenDisplayFuncPtr> XOpenDisplayFunc(libX11, "XOpenDisplay");
+
+    _display = XOpenDisplayFunc(NULL);
+
+    DllFunction<XInternAtomFuncPtr> XInternAtomFunc(libX11, "XInternAtom");
+
+    _atomPid = XInternAtomFunc(_display, (char*)"_NET_WM_PID", True);
+
+    if (_atomPid == None) {
+        return;
+    }
+
+    DllFunction<XDefaultRootWindowFuncPtr> XDefaultRootWindowFunc(libX11, "XDefaultRootWindow");
+
+    searchWindowHelper(XDefaultRootWindowFunc(_display));
+
+    reactivateProcess();
+
+    DllFunction<XCloseDisplayFuncPtr> XCloseDisplayFunc(libX11, "XCloseDisplay");
+
+    XCloseDisplayFunc(_display);
+}
+
+extern "C" {
+typedef int (*XGetWindowPropertyFuncPtr)(Display *display, Window w, Atom property,
+        long long_offset, long long_length, Bool d, Atom req_type, Atom *actual_type_return,
+        int *actual_format_return, unsigned long *nitems_return,
+        unsigned long *bytes_after_return, unsigned char **prop_return);
+
+typedef Status (*XQueryTreeFuncPtr)(Display *display, Window w, Window *root_return,
+        Window *parent_return, Window **children_return, unsigned int *nchildren_return);
+
+typedef int (*XFreeFuncPtr)(void *data);
+}
+
+void ProcessReactivator::searchWindowHelper(Window w) {
+
+    DllFunction<XGetWindowPropertyFuncPtr> XGetWindowPropertyFunc(libX11, "XGetWindowProperty");
+
+    DllFunction<XFreeFuncPtr> XFreeFunc(libX11, "XFree");
+
+    Atom type;
+    int format;
+    unsigned long  num, bytesAfter;
+    unsigned char* propPid = 0;
+    if (Success == XGetWindowPropertyFunc(_display, w, _atomPid, 0, 1, False, XA_CARDINAL,
+                                     &type, &format, &num, &bytesAfter, &propPid)) {
+        if (propPid != 0) {
+            if (_pid == *((pid_t *)propPid)) {
+                _result.push_back(w);
+            }
+            XFreeFunc(propPid);
+        }
+    }
+
+    DllFunction<XQueryTreeFuncPtr> XQueryTreeFunc(libX11, "XQueryTree");
+
+    Window root, parent;
+    Window* child;
+    unsigned int numChildren;
+    if (0 != XQueryTreeFunc(_display, w, &root, &parent, &child, &numChildren)) {
+        for (unsigned int i = 0; i < numChildren; i++) {
+            searchWindowHelper(child[i]);
+        }
+    }
+}
+
+
+extern "C" {
+typedef Status (*XGetWindowAttributesFuncPtr)(Display *display, Window w,
+        XWindowAttributes *window_attributes_return);
+
+typedef Status (*XSendEventFuncPtr)(Display *display, Window w, Bool propagate,
+        long event_mask, XEvent *event_send);
+
+typedef int (*XRaiseWindowFuncPtr)(Display *display, Window w);
+}
+
+void ProcessReactivator::reactivateProcess() {
+
+    DllFunction<XGetWindowAttributesFuncPtr> XGetWindowAttributesFunc(libX11, "XGetWindowAttributes");
+
+    DllFunction<XSendEventFuncPtr> XSendEventFunc(libX11, "XSendEvent");
+
+    DllFunction<XRaiseWindowFuncPtr> XRaiseWindowFunc(libX11, "XRaiseWindow");
+
+    DllFunction<XInternAtomFuncPtr> XInternAtomFunc(libX11, "XInternAtom");
+
+    for (std::list<Window>::const_iterator it = _result.begin(); it != _result.end(); it++) {
+        // try sending an event to activate window,
+        // after that we can try to raise it.
+        XEvent xev;
+        Atom atom = XInternAtomFunc (_display, (char*)"_NET_ACTIVE_WINDOW", False);
+        xev.xclient.type = ClientMessage;
+        xev.xclient.serial = 0;
+        xev.xclient.send_event = True;
+        xev.xclient.display = _display;
+        xev.xclient.window = *it;
+        xev.xclient.message_type = atom;
+        xev.xclient.format = 32;
+        xev.xclient.data.l[0] = 2;
+        xev.xclient.data.l[1] = 0;
+        xev.xclient.data.l[2] = 0;
+        xev.xclient.data.l[3] = 0;
+        xev.xclient.data.l[4] = 0;
+        XWindowAttributes attr;
+        XGetWindowAttributesFunc(_display, *it, &attr);
+        XSendEventFunc(_display, attr.root, False,
+            SubstructureRedirectMask | SubstructureNotifyMask, &xev);
+        XRaiseWindowFunc(_display, *it);
+    }
+}
+
+//--------------------------------------------------------------------------------------------------
+
+#endif // LINUX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/LinuxPlatform.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+
+#ifdef LINUX
+
+#ifndef LINUXPLATFORM_H
+#define LINUXPLATFORM_H
+
+#include "PosixPlatform.h"
+#include "GenericPlatform.h"
+#include "JavaUserPreferences.h"
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <pthread.h>
+#include <list>
+
+
+class LinuxPlatform : virtual public Platform, GenericPlatform, PosixPlatform
+{
+private:
+    pthread_t FMainThread;
+
+protected:
+    virtual TString getTmpDirString();
+
+public:
+    LinuxPlatform(void);
+    virtual ~LinuxPlatform(void);
+
+    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 void SetCurrentDirectory(TString Value);
+    virtual TString GetPackageRootDirectory();
+    virtual TString GetAppDataDirectory();
+
+    virtual TString GetModuleFileName();
+
+    virtual TString GetBundledJVMLibraryFileName(TString RuntimePath);
+
+    virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
+
+    virtual void reactivateAnotherInstance();
+    virtual bool IsMainThread();
+    virtual TPlatformNumber GetMemorySize();
+
+#ifdef DEBUG
+    virtual bool IsNativeDebuggerPresent();
+    virtual int GetProcessID();
+#endif //DEBUG
+};
+
+
+class LinuxJavaUserPreferences : public JavaUserPreferences {
+private:
+    TString GetUserPrefFileName(TString Appid);
+
+public:
+    LinuxJavaUserPreferences(void);
+    ~LinuxJavaUserPreferences(void);
+
+    virtual bool Load(TString Appid);
+};
+
+class ProcessReactivator {
+private:
+    void searchWindowHelper(Window w);
+    void reactivateProcess();
+
+    Library libX11;
+
+    pid_t _pid;
+    Atom _atomPid;
+    Display* _display;
+    std::list<Window> _result;
+public:
+    explicit ProcessReactivator(pid_t pid);
+};
+
+#endif //LINUXPLATFORM_H
+
+#endif //LINUX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/Lock.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Lock.h"
+
+
+Lock::Lock(void) {
+    Initialize();
+}
+
+Lock::Lock(bool Value) {
+    Initialize();
+
+    if (Value == true) {
+        Enter();
+    }
+}
+
+void Lock::Initialize() {
+#ifdef WINDOWS
+    InitializeCriticalSectionAndSpinCount(&FCriticalSection, 0x00000400);
+#endif //WINDOWS
+#ifdef MAC
+    //FMutex =  PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+#endif //MAC
+#ifdef LINUX
+    //FMutex =  PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+#endif //LINUX
+}
+
+Lock::~Lock(void) {
+#ifdef WINDOWS
+    DeleteCriticalSection(&FCriticalSection);
+#endif //WINDOWS
+#ifdef POSIX
+    pthread_mutex_unlock(&FMutex);
+#endif //POSIX
+}
+
+void Lock::Enter() {
+#ifdef WINDOWS
+    EnterCriticalSection(&FCriticalSection);
+#endif //WINDOWS
+#ifdef POSIX
+    pthread_mutex_lock(&FMutex);
+#endif //POSIX
+}
+
+void Lock::Leave() {
+#ifdef WINDOWS
+    LeaveCriticalSection(&FCriticalSection);
+#endif //WINDOWS
+#ifdef POSIX
+    pthread_mutex_unlock(&FMutex);
+#endif //POSIX
+}
+
+bool Lock::TryEnter() {
+    bool result = false;
+#ifdef WINDOWS
+    if (TryEnterCriticalSection (&FCriticalSection) != 0)
+        result = true;
+#endif //WINDOWS
+#ifdef POSIX
+    if (pthread_mutex_lock(&FMutex) == 0)
+        result = true;
+#endif //POSIX
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/Lock.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#ifndef LOCK_H
+#define LOCK_H
+
+#include "Platform.h"
+
+#ifdef POSIX
+#include <pthread.h>
+#endif //POSIX
+
+
+class Lock {
+private:
+#ifdef WINDOWS
+    CRITICAL_SECTION FCriticalSection;
+#endif //WINDOWS
+#ifdef POSIX
+    pthread_mutex_t FMutex;
+#endif //POSIX
+
+    void Initialize();
+
+public:
+    Lock(void);
+    Lock(bool Value);
+    ~Lock(void);
+
+    void Enter();
+    void Leave();
+    bool TryEnter();
+};
+
+#endif //LOCK_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/MacPlatform.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+
+#ifdef MAC
+
+#ifndef MACPLATFORM_H
+#define MACPLATFORM_H
+
+#include "GenericPlatform.h"
+#include "PosixPlatform.h"
+#include "JavaUserPreferences.h"
+
+
+class MacPlatform : virtual public Platform, GenericPlatform, 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 void SetCurrentDirectory(TString Value);
+    virtual TString GetPackageRootDirectory();
+    virtual TString GetAppDataDirectory();
+    virtual TString GetBundledJVMLibraryFileName(TString RuntimePath);
+    virtual TString GetAppName();
+
+    virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
+    virtual TString GetModuleFileName();
+
+    virtual void reactivateAnotherInstance();
+    virtual bool IsMainThread();
+    virtual TPlatformNumber GetMemorySize();
+
+    virtual std::map<TString, TString> GetKeys();
+
+#ifdef DEBUG
+    virtual bool IsNativeDebuggerPresent();
+    virtual int GetProcessID();
+#endif //DEBUG
+};
+
+
+class MacJavaUserPreferences : public JavaUserPreferences {
+public:
+  MacJavaUserPreferences(void);
+
+  virtual bool Load(TString Appid);
+};
+
+#endif //MACPLATFORM_H
+
+#endif //MAC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/Macros.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#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("$APPDIR"), package.GetPackageRootDirectory());
+    macros.AddMacro(_T("$PACKAGEDIR"), package.GetPackageAppDirectory());
+    macros.AddMacro(_T("$LAUNCHERDIR"), package.GetPackageLauncherDirectory());
+    macros.AddMacro(_T("$APPDATADIR"), package.GetAppDataDirectory());
+
+    TString javaHome = FilePath::ExtractFilePath(package.GetJVMLibraryFileName());
+    macros.AddMacro(_T("$JREHOME"), javaHome);
+
+    // App CDS Macros
+    macros.AddMacro(_T("$CACHEDIR"), package.GetAppCDSCacheDirectory());
+
+    // Private macros.
+    TString javaVMLibraryName = FilePath::ExtractFileName(javaHome);
+    macros.AddMacro(_T("$JAVAVMLIBRARYNAME"), javaVMLibraryName);
+}
+
+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.packager/share/native/library/common/Macros.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#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.packager/share/native/library/common/Messages.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Messages.h"
+#include "Platform.h"
+#include "Lock.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(CONFIG_FILE_NOT_FOUND, _T("Configuration file %s is not found."));
+    //FMessages.SetValue(BUNDLED_JVM_NOT_FOUND, _T("$JAVAVMLIBRARYNAME is not found in the bundled runtime."));
+    FMessages.SetValue(APPCDS_CACHE_FILE_NOT_FOUND, _T("Error: AppCDS cache does not exists:\n%s\n"));
+}
+
+Messages& Messages::GetInstance() {
+    //Lock lock;
+    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.packager/share/native/library/common/Messages.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#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.packager/share/native/library/common/OrderedMap.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#ifndef ORDEREDMAP_H
+#define ORDEREDMAP_H
+
+#ifdef WINDOWS
+#pragma warning(disable:4522) 
+#endif
+
+#include <map>
+#include <vector>
+#include <assert.h>
+#include <stdexcept>
+
+#include <iostream>
+
+
+template <typename _T1, typename _T2>
+struct pair
+{
+    typedef _T1 first_type;
+    typedef _T2 second_type;
+
+    first_type first;
+    second_type second;
+
+    pair(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 pair<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);
+    }
+
+    ~OrderedMap() {
+        Clear();
+    }
+
+    void SetAllowDuplicates(bool Value) {
+        FAllowDuplicates = Value;
+    }
+
+    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;
+    }
+
+    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();
+        Append(Value);
+        return *this;
+    }
+
+    OrderedMap& operator= (const OrderedMap &Value) {
+        Clear();
+        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.packager/share/native/library/common/Package.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,656 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Package.h"
+#include "Lock.h"
+#include "Helpers.h"
+#include "JavaUserPreferences.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;
+}
+
+bool Package::CheckForSingleInstance() {
+    Platform& platform = Platform::GetInstance();
+#ifdef MAC
+    if (platform.IsMainThread()) {
+        return false;
+    }
+#endif
+    if (FInitialized == true) {
+        // everything must be initialised at this point
+        return false;
+    }
+    TString appName;
+    TString appVersion;
+    AutoFreePtr<ISectionalPropertyContainer> config = platform.GetConfigFile(platform.GetConfigFileName());
+    std::map<TString, TString> keys = platform.GetKeys();
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[APP_NAME_KEY], appName);
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[CONFIG_VERSION], appVersion);
+    TString singleInstance;
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[CONFIG_APPLICATION_INSTANCE], singleInstance);
+    if (singleInstance == _T("single")) {
+        TString uniqueID = appName + FBootFields->FAppID + appVersion;
+        // if another instance is running, later we can try to reactivate it
+        return platform.CheckForSingleInstance(uniqueID);
+    }
+    return false;
+}
+
+void Package::Initialize() {
+    if (FInitialized == true) {
+        return;
+    }
+
+    Platform& platform = Platform::GetInstance();
+
+    FBootFields = new PackageBootFields();
+    FDebugging = dsNone;
+
+    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[CONFIG_APP_ID_KEY], FBootFields->FAppID);
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[PACKAGER_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::IncludeTrailingSeparater(GetPackageAppDirectory()) +
+                            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::IncludeTrailingSeparater(GetPackageAppDirectory()) +
+                                             FilePath::FixPathForPlatform(FBootFields->FSplashScreenFileName);
+
+        if (FilePath::FileExists(FBootFields->FSplashScreenFileName) == false) {
+            FBootFields->FSplashScreenFileName = _T("");
+        }
+    }
+
+    // Runtime.
+    config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[JVM_RUNTIME_KEY], FBootFields->FJVMRuntimeDirectory);
+
+    // Read jvmargs.
+    PromoteAppCDSState(config);
+    ReadJVMArgs(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);
+        }
+    }
+
+    // Read jvmuserarg defaults.
+    config->GetSection(keys[CONFIG_SECTION_JVMUSEROPTIONS], FDefaultJVMUserArgs);
+
+    // Load JVM user overrides.
+    TString jvmUserArgsConfigFileName = GetJVMUserArgsConfigFileName();
+
+    if (FilePath::FileExists(jvmUserArgsConfigFileName) == true) {
+        // Load new location for user VM overrides.
+        IniFile userConfig;
+
+        if (userConfig.LoadFromFile(jvmUserArgsConfigFileName) == false) {
+            // New property file format was not found, attempt to load old property file format.
+            userConfig.GetSection(keys[CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS], FJVMUserArgsOverrides);
+        }
+
+        userConfig.GetSection(keys[CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS], FJVMUserArgsOverrides);
+    }
+    else {
+        // Attemp to load java.util.prefs for legacy JVM user overrides.
+        AutoFreePtr<JavaUserPreferences> javaPreferences(JavaUserPreferences::CreateInstance());
+
+        if (javaPreferences->Load(GetAppID()) == true) {
+            FJVMUserArgsOverrides = javaPreferences->GetData();
+        }
+    }
+
+    // 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);
+    }
+
+    MergeJVMDefaultsWithOverrides();
+}
+
+void Package::Clear() {
+    FreeBootFields();
+    FJVMUserArgsOverrides.Clear();
+    FDefaultJVMUserArgs.Clear();
+    FJVMUserArgs.Clear();
+    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 "AppCDSJVMOptions" section is present
+//    -> cdsAuto If "AppCDSJVMOptions" 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_APPCDSJVMOPTIONS]) == 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::ReadJVMArgs(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_JVMOPTIONS], FBootFields->FJVMArgs);
+            break;
+        }
+
+        case cdsGenCache: {
+            Config->GetSection(keys[CONFIG_SECTION_APPCDSGENERATECACHEJVMOPTIONS], FBootFields->FJVMArgs);
+            break;
+        }
+
+        case cdsAuto:
+        case cdsEnabled: {
+            if (Config->GetValue(keys[CONFIG_SECTION_APPCDSJVMOPTIONS],
+                                 _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_APPCDSJVMOPTIONS],
+                                     _T( "-XX:SharedArchiveFile"), FBootFields->FAppCDSCacheFileName);
+                    }
+                }
+
+                Config->GetSection(keys[CONFIG_SECTION_APPCDSJVMOPTIONS], FBootFields->FJVMArgs);
+            }
+
+            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::GetJVMArgs() {
+    return FBootFields->FJVMArgs;
+}
+
+OrderedMap<TString, TString> Package::GetDefaultJVMUserArgs() {
+    return FDefaultJVMUserArgs;
+}
+
+OrderedMap<TString, TString> Package::GetJVMUserArgOverrides() {
+    return FJVMUserArgsOverrides;
+}
+
+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;
+}
+
+void Package::SetJVMUserArgOverrides(OrderedMap<TString, TString> Value) {
+    OrderedMap<TString, TString> defaults = GetDefaultJVMUserArgs();
+    OrderedMap<TString, TString> overrides = Value;
+
+    // 1. Remove entries in the overrides that are the same as the defaults.
+    std::vector<TString> overrideKeys = GetKeysThatAreNotDuplicates(defaults, overrides);
+
+    // 2. Create an ordered map from the overrides that weren't removed.
+    FJVMUserArgsOverrides = CreateOrderedMapFromKeyList(overrides, overrideKeys);
+
+    // 3. Overwrite JVM user config overrides with provided key/value pair.
+    SaveJVMUserArgOverrides(FJVMUserArgsOverrides);
+
+    // 4. Merge defaults and overrides to produce FJVMUserArgs.
+    MergeJVMDefaultsWithOverrides();
+}
+
+void Package::SaveJVMUserArgOverrides(OrderedMap<TString, TString> Data) {
+    IniFile userConfig;
+    Platform& platform = Platform::GetInstance();
+    std::map<TString, TString> keys = platform.GetKeys();
+    userConfig.AppendSection(keys[CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS], Data);
+    userConfig.SaveToFile(GetJVMUserArgsConfigFileName());
+}
+
+OrderedMap<TString, TString> Package::GetJVMUserArgs() {
+    return FJVMUserArgs;
+}
+
+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;
+}
+
+void Package::MergeJVMDefaultsWithOverrides() {
+    // Merge jvmuserarg defaults and jvmuserarg overrides to populate FJVMUserArgs.
+    // 1. If the key is in the config file and not the java.user.preferences the default value is used,
+    //    the one from the config file.
+    // 2. If the key is in the java.user.preferences then the value from the java.user.preferences is used and
+    //    the config file value is ignored.
+    // 3. If the key is not in the config file but it is in the java.user.preferences then it is added anyway.
+    //    And if it is removed it won't show back up.
+    FJVMUserArgs.Clear();
+    FJVMUserArgs.Append(FDefaultJVMUserArgs);
+
+    OrderedMap<TString, TString> overrides = GetJVMUserArgOverrides();
+
+    // 1. Iterate over all elements in overrides to see if any items
+    //    override a default value.
+    std::vector<TString> keys = GetKeysThatAreNotOverridesOfDefaultValues(FJVMUserArgs, overrides);
+
+
+    // 2. All remaining items in overrides are appended to the end.
+    for (unsigned int index = 0; index< keys.size(); index++) {
+        TString key = keys[index];
+        TString value;
+
+        if (overrides.GetValue(key, value) == true) {
+            FJVMUserArgs.Append(key, value);
+        }
+    }
+}
+
+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::GetJVMUserArgsConfigFileName() {
+    if (FJVMUserArgsConfigFileName.empty()) {
+        Platform& platform = Platform::GetInstance();
+
+        FJVMUserArgsConfigFileName = FilePath::IncludeTrailingSeparater(platform.GetAppDataDirectory()) +
+                                        FilePath::IncludeTrailingSeparater(GetPackageAppDataDirectory()) +
+                                        FilePath::IncludeTrailingSeparater(_T("packager")) +
+                                        _T("jvmuserargs.cfg");
+    }
+
+    return FJVMUserArgsConfigFileName;
+}
+
+TString Package::GetAppCDSCacheDirectory() {
+    if (FAppCDSCacheDirectory.empty()) {
+        Platform& platform = Platform::GetInstance();
+        FAppCDSCacheDirectory = FilePath::IncludeTrailingSeparater(platform.GetAppDataDirectory()) +
+                                FilePath::IncludeTrailingSeparater(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::GetAppID() {
+    assert(FBootFields != NULL);
+    return FBootFields->FAppID;
+}
+
+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::GetJVMLibraryFileName() {
+    assert(FBootFields != NULL);
+
+    if (FBootFields->FJVMLibraryFileName.empty() == true) {
+        Platform& platform = Platform::GetInstance();
+        Macros& macros = Macros::GetInstance();
+        TString jvmRuntimePath = macros.ExpandMacros(GetJVMRuntimeDirectory());
+        FBootFields->FJVMLibraryFileName = platform.GetBundledJVMLibraryFileName(jvmRuntimePath);
+    }
+
+    return FBootFields->FJVMLibraryFileName;
+}
+
+TString Package::GetJVMRuntimeDirectory() {
+    assert(FBootFields != NULL);
+    return FBootFields->FJVMRuntimeDirectory;
+}
+
+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.packager/share/native/library/common/Package.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#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> FJVMArgs;
+    std::list<TString> FArgs;
+
+    TString FPackageRootDirectory;
+    TString FPackageAppDirectory;
+    TString FPackageLauncherDirectory;
+    TString FAppDataDirectory;
+    TString FAppID;
+    TString FPackageAppDataDirectory;
+    TString FClassPath;
+    TString FModulePath;
+    TString FMainJar;
+    TString FMainModule;
+    TString FMainClassName;
+    TString FJVMRuntimeDirectory;
+    TString FJVMLibraryFileName;
+    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 FJVMUserArgsConfigFileName;
+    TString FAppCDSCacheDirectory;
+
+    DebugState FDebugging;
+
+    OrderedMap<TString, TString> FJVMUserArgsOverrides;
+    OrderedMap<TString, TString> FDefaultJVMUserArgs; // Contains JVM user defaults
+    OrderedMap<TString, TString> FJVMUserArgs; // Contains a merge of JVM defaults and user overrides
+
+
+    Package(void);
+
+    //void Initialize();
+    void MergeJVMDefaultsWithOverrides();
+    TString GetMainJar();
+    void SaveJVMUserArgOverrides(OrderedMap<TString, TString> Data);
+    void ReadJVMArgs(ISectionalPropertyContainer* Config);
+    void PromoteAppCDSState(ISectionalPropertyContainer* Config);
+
+public:
+    static Package& GetInstance();
+    ~Package(void);
+
+    void Initialize();
+    void Clear();
+    void FreeBootFields();
+    bool CheckForSingleInstance();
+
+    void SetCommandLineArguments(int argc, TCHAR* argv[]);
+
+    OrderedMap<TString, TString> GetJVMArgs();
+    OrderedMap<TString, TString> GetDefaultJVMUserArgs();
+    OrderedMap<TString, TString> GetJVMUserArgOverrides();
+    void SetJVMUserArgOverrides(OrderedMap<TString, TString> Value);
+    OrderedMap<TString, TString> GetJVMUserArgs();
+    TString GetMainModule();
+
+    std::list<TString> GetArgs();
+
+    TString GetPackageRootDirectory();
+    TString GetPackageAppDirectory();
+    TString GetPackageLauncherDirectory();
+    TString GetAppDataDirectory();
+
+    TString GetJVMUserArgsConfigFileName();
+    TString GetAppCDSCacheDirectory();
+    TString GetAppCDSCacheFileName();
+
+    TString GetAppID();
+    TString GetPackageAppDataDirectory();
+    TString GetClassPath();
+    TString GetModulePath();
+    TString GetMainClassName();
+    TString GetJVMLibraryFileName();
+    TString GetJVMRuntimeDirectory();
+    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.packager/share/native/library/common/Platform.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+#include "Lock.h"
+#include "Messages.h"
+
+#include "WindowsPlatform.h"
+#include "LinuxPlatform.h"
+#include "MacPlatform.h"
+
+
+// Environment
+StaticReadProperty<TString, &Environment::GetNewLine> Environment::NewLine;
+
+
+//--------------------------------------------------------------------------------------------------
+
+Platform& Platform::GetInstance() {
+    //Lock lock(true);
+#ifdef WINDOWS
+    static WindowsPlatform instance;
+#endif // WINDOWS
+#ifdef LINUX
+    static LinuxPlatform instance;
+#endif // LINUX
+#ifdef MAC
+    static MacPlatform instance;
+#endif // MAC
+    return instance;
+}
+
+//--------------------------------------------------------------------------------------------------
+
+
+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);
+            }
+        }
+    }
+}
+//--------------------------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/Platform.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+#include "OrderedMap.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string>
+#include <map>
+#include <list>
+#include <vector>
+
+
+#ifdef WIN32
+#ifndef WINDOWS
+#define WINDOWS
+#endif
+#endif //WIN32
+
+#ifdef __APPLE__
+#define MAC
+#define POSIX
+#endif //__APPLE__
+
+
+#ifdef __linux
+#ifndef LINUX
+#define LINUX
+#endif
+#endif //__linux
+
+#ifdef LINUX
+#define POSIX
+#endif //LINUX
+
+
+
+#ifdef WINDOWS
+// 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>
+
+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;
+
+#if defined _DEBUG && !defined DEBUG
+    #define DEBUG
+#endif
+
+#endif //WINDOWS
+
+
+#ifdef POSIX
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <libgen.h>
+
+#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*
+#endif //POSIX
+
+
+// Config file sections
+#define CONFIG_SECTION_APPLICATION                   _T("CONFIG_SECTION_APPLICATION")
+#define CONFIG_SECTION_JVMOPTIONS                    _T("CONFIG_SECTION_JVMOPTIONS")
+#define CONFIG_SECTION_JVMUSEROPTIONS                _T("CONFIG_SECTION_JVMUSEROPTIONS")
+#define CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS       _T("CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS")
+#define CONFIG_SECTION_APPCDSJVMOPTIONS              _T("CONFIG_SECTION_APPCDSJVMOPTIONS")
+#define CONFIG_SECTION_APPCDSGENERATECACHEJVMOPTIONS _T("CONFIG_SECTION_APPCDSGENERATECACHEJVMOPTIONS")
+#define CONFIG_SECTION_ARGOPTIONS                    _T("CONFIG_SECTION_ARGOPTIONS")
+
+// 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_ID_KEY         _T("CONFIG_APP_ID_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 JVM_RUNTIME_KEY           _T("JVM_RUNTIME_KEY")
+#define PACKAGER_APP_DATA_DIR     _T("CONFIG_APP_IDENTIFIER")
+
+
+
+typedef void* Module;
+typedef void* Procedure;
+
+
+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 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;
+    }
+};
+
+
+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;
+};
+
+class Environment {
+private:
+    Environment() {
+    }
+
+public:
+    static TString GetNewLine() {
+#ifdef WINDOWS
+        return _T("\r\n");
+#endif //WINDOWS
+#ifdef POSIX
+        return _T("\n");
+#endif //POSIX
+    }
+
+    static StaticReadProperty<TString, &Environment::GetNewLine> NewLine;
+};
+
+
+enum DebugState {dsNone, dsNative, dsJava};
+enum MessageResponse {mrOK, mrCancel};
+enum AppCDSState {cdsUninitialized, cdsDisabled, cdsEnabled, cdsAuto, cdsGenCache};
+
+class Platform {
+private:
+    AppCDSState FAppCDSState;
+
+protected:
+    TProcessID singleInstanceProcessId;
+
+    Platform(void): FAppCDSState(cdsUninitialized), singleInstanceProcessId(0) {
+    }
+
+public:
+    AppCDSState GetAppCDSState() { return FAppCDSState; }
+    void SetAppCDSState(AppCDSState Value) { FAppCDSState = Value; }
+    TProcessID GetSingleInstanceProcessId() { return singleInstanceProcessId; }
+
+    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;
+//    virtual MessageResponse ShowResponseMessage(TString description) = 0;
+
+    virtual void SetCurrentDirectory(TString Value) = 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\<app.identifier>\packager\jvmuserargs.cfg
+    // Linux=~/.local/<app.identifier>/packager/jvmuserargs.cfg
+    // Mac=~/Library/Application Support/<app.identifier>/packager/jvmuserargs.cfg
+    virtual TString GetAppDataDirectory() = 0;
+
+    virtual TString GetPackageAppDirectory() = 0;
+    virtual TString GetPackageLauncherDirectory() = 0;
+    virtual TString GetAppName() = 0;
+
+    virtual TString GetConfigFileName() = 0;
+
+    virtual TString GetBundledJVMLibraryFileName(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;
+    virtual std::vector<TString> GetLibraryImports(const TString FileName) = 0;
+    virtual std::vector<TString> FilterOutRuntimeDependenciesForPlatform(std::vector<TString> Imports) = 0;
+
+    // Caller must free result.
+    virtual Process* CreateProcess() = 0;
+
+    virtual bool IsMainThread() = 0;
+    virtual bool CheckForSingleInstance(TString Name) = 0;
+    virtual void reactivateAnotherInstance() = 0;
+
+    // Returns megabytes.
+    virtual TPlatformNumber GetMemorySize() = 0;
+
+    virtual std::map<TString, TString> GetKeys() = 0;
+
+    virtual std::list<TString> LoadFromFile(TString FileName) = 0;
+    virtual void SaveToFile(TString FileName, std::list<TString> Contents, bool ownerOnly) = 0;
+
+    virtual TString GetTempDirectory() = 0;
+
+#ifdef DEBUG
+    virtual DebugState GetDebugState() = 0;
+    virtual int GetProcessID() = 0;
+    virtual bool IsNativeDebuggerPresent() = 0;
+#endif //DEBUG
+};
+
+
+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 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; }
+};
+
+class FileNotFoundException: public Exception {
+public:
+    explicit FileNotFoundException(const TString Message) : Exception(Message) {}
+};
+
+#endif //PLATFORM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/PlatformString.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "PlatformString.h"
+
+#include "Java.h"
+#include "Helpers.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <sstream>
+#include <string.h>
+
+#include "jni.h"
+
+//--------------------------------------------------------------------------------------------------
+
+#ifdef MAC
+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;
+}
+#endif //MAC
+
+//--------------------------------------------------------------------------------------------------
+
+#ifdef MAC
+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;
+}
+#endif //MAC
+
+
+//--------------------------------------------------------------------------------------------------
+
+
+void PlatformString::initialize() {
+    FWideTStringToFree = NULL;
+    FLength = 0;
+    FData = NULL;
+}
+
+void PlatformString::CopyString(char *Destination, size_t NumberOfElements, const char *Source) {
+#ifdef WINDOWS
+    strcpy_s(Destination, NumberOfElements, Source);
+#endif //WINDOWS
+#ifdef POSIX
+    strncpy(Destination, Source, NumberOfElements);
+#endif //POSIX
+
+    if (NumberOfElements > 0) {
+        Destination[NumberOfElements - 1] = '\0';
+    }
+}
+
+void PlatformString::CopyString(wchar_t *Destination, size_t NumberOfElements, const wchar_t *Source) {
+#ifdef WINDOWS
+    wcscpy_s(Destination, NumberOfElements, Source);
+#endif //WINDOWS
+#ifdef POSIX
+    wcsncpy(Destination, Source, NumberOfElements);
+#endif //POSIX
+
+    if (NumberOfElements > 0) {
+        Destination[NumberOfElements - 1] = '\0';
+    }
+}
+
+PlatformString::PlatformString(void) {
+    initialize();
+}
+
+PlatformString::~PlatformString(void) {
+    if (FData != NULL) {
+        delete[] FData;
+    }
+
+    if (FWideTStringToFree != NULL) {
+        delete[] FWideTStringToFree;
+    }
+}
+
+// Owner must free the return value.
+MultibyteString PlatformString::WideStringToMultibyteString(const wchar_t* value) {
+    MultibyteString result;
+    size_t count = 0;
+
+#ifdef WINDOWS
+    wcstombs_s(&count, NULL, 0, value, 0);
+
+    if (count > 0) {
+        result.data = new char[count + 1];
+        wcstombs_s(&result.length, result.data, count, value, count);
+
+#endif //WINDOWS
+#ifdef POSIX
+    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);
+#endif //POSIX
+    }
+
+    return result;
+}
+
+// Owner must free the return value.
+WideString PlatformString::MultibyteStringToWideString(const char* value) {
+    WideString result;
+    size_t count = 0;
+
+#ifdef WINDOWS
+    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);
+#endif // WINDOWS
+#ifdef POSIX
+    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);
+#endif //POSIX
+    }
+
+    return result;
+}
+
+PlatformString::PlatformString(const PlatformString &value) {
+    initialize();
+    FLength = value.FLength;
+    FData = new char[FLength + 1];
+    PlatformString::CopyString(FData, FLength + 1, value.FData);
+}
+
+PlatformString::PlatformString(const char* value) {
+    initialize();
+    FLength = strlen(value);
+    FData = new char[FLength + 1];
+    PlatformString::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];
+    PlatformString::CopyString(FData, FLength + 1, s.c_str());
+}
+
+PlatformString::PlatformString(const wchar_t* value) {
+    initialize();
+    MultibyteString temp = 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];
+    PlatformString::CopyString(FData, FLength + 1, lvalue);
+}
+
+PlatformString::PlatformString(const std::wstring &value) {
+    initialize();
+    const wchar_t* lvalue = value.data();
+    MultibyteString temp = WideStringToMultibyteString(lvalue);
+    FLength = temp.length;
+    FData = temp.data;
+}
+
+PlatformString::PlatformString(JNIEnv *env, jstring value) {
+    initialize();
+
+    if (env != NULL) {
+        const char* lvalue = env->GetStringUTFChars(value, JNI_FALSE);
+
+        if (lvalue == NULL || env->ExceptionCheck() == JNI_TRUE) {
+            throw JavaException();
+        }
+
+        if (lvalue != NULL) {
+            FLength = env->GetStringUTFLength(value);
+
+            if (env->ExceptionCheck() == JNI_TRUE) {
+                throw JavaException();
+            }
+
+            FData = new char[FLength + 1];
+            PlatformString::CopyString(FData, FLength + 1, lvalue);
+
+            env->ReleaseStringUTFChars(value, lvalue);
+
+            if (env->ExceptionCheck() == JNI_TRUE) {
+                throw JavaException();
+            }
+        }
+    }
+}
+
+TString PlatformString::Format(const TString value, ...) {
+//std::string PlatformString::Format(std::string 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 = 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;
+}
+
+jstring PlatformString::toJString(JNIEnv *env) {
+    jstring result = NULL;
+
+    if (env != NULL) {
+        result = env->NewStringUTF(c_str());
+
+        if (result == NULL || env->ExceptionCheck() == JNI_TRUE) {
+            throw JavaException();
+        }
+    }
+
+    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];
+    PlatformString::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];
+    PlatformString::CopyString(result, length + 1, Value);
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/PlatformString.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#ifndef PLATFORMSTRING_H
+#define PLATFORMSTRING_H
+
+
+#include <string>
+#include <list>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "jni.h"
+#include "Platform.h"
+
+
+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; }
+};
+
+
+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; }
+
+    void Resize(size_t Size) {
+        FSize = Size;
+
+        if (FData != NULL) {
+            delete[] FData;
+            FData = NULL;
+        }
+
+        if (FSize != 0) {
+            FData = new T[FSize];
+            Zero();
+        }
+    }
+
+    void Zero() {
+        memset(FData, 0, FSize * sizeof(T));
+    }
+
+    T& operator[](size_t index) {
+        return FData[index];
+    }
+};
+
+
+#ifdef MAC
+// 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 //MAC
+
+#ifdef LINUX
+#define StringToFileSystemString PlatformString
+#define FileSystemStringToString PlatformString
+#endif //LINUX
+
+
+class PlatformString {
+private:
+    char* FData; // Stored as UTF-8
+    size_t FLength;
+    wchar_t* FWideTStringToFree;
+
+    void initialize();
+
+    // 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);
+
+// 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(JNIEnv *env, jstring 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();
+    jstring toJString(JNIEnv *env);
+    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.packager/share/native/library/common/PlatformThread.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "PlatformThread.h"
+
+
+PlatformThread::PlatformThread(void) {
+}
+
+PlatformThread::~PlatformThread(void) {
+    Wait();
+    Terminate();
+}
+
+#ifdef WINDOWS
+DWORD WINAPI PlatformThread::Do(LPVOID Data) {
+    PlatformThread* self = (PlatformThread*)Data;
+    self->Execute();
+    return 0;
+}
+#endif //WINDOWS
+#ifdef POSIX
+void* PlatformThread::Do(void *Data) {
+    PlatformThread* self = (PlatformThread*)Data;
+    self->Execute();
+    pthread_exit(NULL);
+}
+#endif //POSIX
+
+void PlatformThread::Run() {
+#ifdef WINDOWS
+    FHandle = CreateThread(NULL, 0, Do, this, 0, &FThreadID);
+#endif //WINDOWS
+#ifdef POSIX
+    pthread_create(&FHandle, NULL, Do, this);
+#endif //POSIX
+}
+
+void PlatformThread::Terminate() {
+#ifdef WINDOWS
+    CloseHandle(FHandle);
+#endif //WINDOWS
+#ifdef POSIX
+    pthread_cancel(FHandle);
+#endif //POSIX
+}
+
+void PlatformThread::Wait() {
+#ifdef WINDOWS
+    WaitForSingleObject(FHandle, INFINITE);
+#endif //WINDOWS
+#ifdef POSIX
+    pthread_join(FHandle, NULL);
+#endif //POSIX
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/PlatformThread.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+
+#ifndef PLATFORMTHREAD_H
+#define PLATFORMTHREAD_H
+
+#ifdef POSIX
+#include <pthread.h>
+#endif //POSIX
+
+
+class PlatformThread {
+private:
+#ifdef WINDOWS
+    HANDLE FHandle;
+    DWORD FThreadID;
+    static DWORD WINAPI Do(LPVOID lpParam);
+#endif //WINDOWS
+#ifdef POSIX
+    pthread_t FHandle;
+    static void* Do(void *threadid);
+#endif //POSIX
+
+protected:
+    // Never call directly. Override this method and this is your code that runs in a thread.
+    virtual void Execute() = 0;
+
+public:
+    PlatformThread(void);
+    virtual ~PlatformThread(void);
+
+    void Run();
+    void Terminate();
+    void Wait();
+};
+
+#endif //PLATFORMTHREAD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/PosixPlatform.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "PosixPlatform.h"
+
+#ifdef POSIX
+
+#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 <errno.h>
+#include <limits.h>
+#include <pwd.h>
+#include <iostream>
+#include <algorithm>
+#include <dlfcn.h>
+#include <signal.h>
+
+
+PosixPlatform::PosixPlatform(void) {
+}
+
+PosixPlatform::~PosixPlatform(void) {
+    if (!SingleInstanceFile.empty()) {
+        unlink(SingleInstanceFile.c_str());
+    }
+}
+
+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;
+}
+
+// returns true if another instance is already running.
+// if false, we need to continue regular launch.
+bool PosixPlatform::CheckForSingleInstance(TString appName) {
+    TString tmpDir = GetTempDirectory();
+    if (tmpDir.empty()) {
+        printf("Unable to check for single instance.\n");
+        return false;
+    }
+
+    TString lockFile = tmpDir + "/" + fixName(appName);
+    SingleInstanceFile = lockFile;
+    int pid_file = open(lockFile.c_str(), O_CREAT | O_RDWR, 0666);
+    int rc = flock(pid_file, LOCK_EX | LOCK_NB);
+
+    if (rc) {
+        if (EWOULDBLOCK == errno) {
+            // another instance is running
+            pid_t pid = 0;
+            read(pid_file, (void*)&pid, sizeof(pid_t));
+            printf("Another instance is running PID: %d\n", pid);
+            if (pid != 0) {
+                singleInstanceProcessId = pid;
+                SingleInstanceFile.clear();
+                return true;
+            }
+        } else {
+            printf("Unable to check for single instance.\n");
+        }
+    } else {
+        // It is the first instance.
+        pid_t pid = getpid();
+        write(pid_file, (void*)&pid, sizeof(pid_t));
+    }
+
+    return false;
+}
+
+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;
+}
+
+//MessageResponse PosixPlatform::ShowResponseMessageB(TString description) {
+//    TString appname = GetModuleFileName();
+//    appname = FilePath::ExtractFileName(appname);
+//    return ShowResponseMessage(appname, description);
+//}
+
+void PosixPlatform::SetCurrentDirectory(TString Value) {
+    chdir(StringToFileSystemString(Value));
+}
+
+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));
+}
+
+std::vector<std::string> PosixPlatform::GetLibraryImports(const TString FileName) {
+ std::vector<TString> result;
+ return result;
+}
+
+std::vector<TString> PosixPlatform::FilterOutRuntimeDependenciesForPlatform(std::vector<TString> Imports) {
+ std::vector<TString> result;
+ return result;
+}
+
+Process* PosixPlatform::CreateProcess() {
+    return new PosixProcess();
+}
+
+//--------------------------------------------------------------------------------------------------
+
+
+PosixProcess::PosixProcess() : Process() {
+    FChildPID = 0;
+    FRunning = false;
+    FOutputHandle = 0;
+    FInputHandle = 0;
+}
+
+PosixProcess::~PosixProcess() {
+    Terminate();
+}
+
+void PosixProcess::Cleanup() {
+    if (FOutputHandle != 0) {
+        close(FOutputHandle);
+        FOutputHandle = 0;
+    }
+
+    if (FInputHandle != 0) {
+        close(FInputHandle);
+        FInputHandle = 0;
+    }
+
+#ifdef MAC
+    sigaction(SIGINT, &savintr, (struct sigaction *)0);
+    sigaction(SIGQUIT, &savequit, (struct sigaction *)0);
+    sigprocmask(SIG_SETMASK, &saveblock, (sigset_t *)0);
+#endif //MAC
+}
+
+bool PosixProcess::ReadOutput() {
+    bool result = false;
+
+    if (FOutputHandle != 0 && IsRunning() == true) {
+        char buffer[4096];
+        //select(p[0] + 1, &rfds, NULL, NULL, NULL);
+
+        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 {
+            if (buffer[count] == EOF) {
+                buffer[count] = '\0';
+            }
+
+            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;
+}
+
+#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) {
+            //perror("pipe");
+            //exit(1);
+            return false;
+        }
+
+        struct sigaction sa;
+        sa.sa_handler = SIG_IGN;
+        sigemptyset(&sa.sa_mask);
+        sa.sa_flags = 0;
+#ifdef MAC
+        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);
+#endif //MAC
+        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(FOutputHandle, STDOUT_FILENO);
+//            dup2(FInputHandle, STDIN_FILENO);
+//            close(FOutputHandle);
+//            close(FInputHandle);
+
+            dup2(handles[PIPE_READ], STDIN_FILENO);
+            dup2(handles[PIPE_WRITE], STDOUT_FILENO);
+//            setvbuf(stdout,NULL,_IONBF,0);
+//            setvbuf(stdin,NULL,_IONBF,0);
+
+            close(handles[PIPE_READ]);
+            close(handles[PIPE_WRITE]);
+
+            execl("/bin/sh", "sh", "-c", command.data(), (char *)0);
+
+            _exit(127);
+        } else {
+//            close(handles[PIPE_READ]);
+//            close(handles[PIPE_WRITE]);
+
+//            close(output[1]);
+//            int nbytes = read(output[0], foo, sizeof(foo));
+//            printf("Output: (%.*s)\n", nbytes, foo);
+//            wait(NULL);
+            FOutputHandle = handles[PIPE_READ];
+            FInputHandle = handles[PIPE_WRITE];
+
+            if (AWait == true) {
+                ReadOutput();
+                Wait();
+                Cleanup();
+                FRunning = false;
+                result = true;
+            }
+            else {
+                result = true;
+            }
+        }
+    }
+
+    return result;
+}
+
+bool PosixProcess::Wait() {
+    bool result = false;
+
+    int status = 0;
+    pid_t wpid = 0;
+
+#ifdef LINUX
+    wait();
+#endif
+#ifdef MAC
+    wpid = wait(&status);
+#endif
+
+    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) {
+        write(FInputHandle, Value.data(), Value.size());
+    }
+}
+
+std::list<TString> PosixProcess::GetOutput() {
+    ReadOutput();
+    return Process::GetOutput();
+}
+
+#endif //POSIX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/PosixPlatform.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+
+#ifdef POSIX
+
+#ifndef POSIXPLATFORM_H
+#define POSIXPLATFORM_H
+
+
+class PosixPlatform : virtual public Platform {
+protected:
+    TString SingleInstanceFile;
+
+    TString fixName(const TString& name);
+
+    virtual TString getTmpDirString() = 0;
+
+public:
+    PosixPlatform(void);
+    virtual ~PosixPlatform(void);
+
+public:
+    virtual MessageResponse ShowResponseMessage(TString title, TString description);
+    //virtual MessageResponse ShowResponseMessageB(TString description);
+
+    virtual void SetCurrentDirectory(TString Value);
+
+    virtual bool CheckForSingleInstance(TString Name);
+    virtual Module LoadLibrary(TString FileName);
+    virtual void FreeLibrary(Module AModule);
+    virtual Procedure GetProcAddress(Module AModule, std::string MethodName);
+    virtual std::vector<TString> GetLibraryImports(const TString FileName);
+    virtual std::vector<TString> FilterOutRuntimeDependenciesForPlatform(std::vector<TString> Imports);
+
+    virtual Process* CreateProcess();
+    virtual TString GetTempDirectory();
+};
+
+
+class PosixProcess : public Process {
+private:
+    pid_t FChildPID;
+    sigset_t saveblock;
+    int FOutputHandle;
+    int FInputHandle;
+#ifdef MAC
+    struct sigaction savintr, savequit;
+#endif //MAC
+    bool FRunning;
+
+    void Cleanup();
+    bool ReadOutput();
+    //static void ProcessOutput(Process *Instance, std::vector<TString> Output);
+
+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
+#endif //POSX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/PropertyFile.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#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(std::map<TString, TString> Value) : PropertyContainer() {
+//    FData.Append(Value);
+//}
+
+PropertyFile::PropertyFile(const 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;
+}
+
+//void PropertyFile::Assign(std::map<TString, TString> Value) {
+//    FData.Clear();
+//    FData.Assign(Value);
+//    SetModified(true);
+//}
+
+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();
+}
+
+//std::vector<TString> PropertyFile::GetKeys() {
+//    return FData.GetKeys();
+//}
+
+OrderedMap<TString, TString> PropertyFile::GetData() {
+    return FData;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/PropertyFile.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#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(const PropertyFile &Value);
+    virtual ~PropertyFile(void);
+
+    bool IsModified();
+    bool GetReadOnly();
+    void SetReadOnly(bool Value);
+
+    //void Assign(std::map<TString, TString> 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();
+    //virtual std::vector<TString> GetKeys();
+};
+
+#endif //PROPERTYFILE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/WindowsPlatform.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,890 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+
+#ifdef WINDOWS
+
+#include "JavaVirtualMachine.h"
+#include "WindowsPlatform.h"
+#include "Package.h"
+#include "Helpers.h"
+#include "PlatformString.h"
+#include "Macros.h"
+
+#include <map>
+#include <vector>
+#include <regex>
+
+#define WINDOWS_PACKAGER_TMP_DIR L"\\AppData\\LocalLow\\Sun\\Java\\Packager\\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);
+
+            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;
+                    buffer.Resize(length);
+                    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) {
+            buffer.Resize(length + 1);
+            dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, (LPBYTE)buffer.GetData(), &length);
+            result = buffer.GetData();
+        }
+
+        return result;
+    }
+};
+
+//--------------------------------------------------------------------------------------------------
+
+WindowsPlatform::WindowsPlatform(void) : Platform(), GenericPlatform() {
+    FMainThread = ::GetCurrentThreadId();
+}
+
+WindowsPlatform::~WindowsPlatform(void) {
+}
+
+TCHAR* WindowsPlatform::ConvertStringToFileSystemString(TCHAR* Source, bool &release) {
+    // Not Implemented.
+    return NULL;
+}
+
+TCHAR* WindowsPlatform::ConvertFileSystemStringToString(TCHAR* Source, bool &release) {
+    // Not Implemented.
+    return NULL;
+}
+
+void WindowsPlatform::SetCurrentDirectory(TString Value) {
+    _wchdir(Value.data());
+}
+
+TString WindowsPlatform::GetPackageRootDirectory() {
+    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;
+}
+
+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;
+}
+
+//MessageResponse WindowsPlatform::ShowResponseMessage(TString description) {
+//    TString appname = GetModuleFileName();
+//    appname = FilePath::ExtractFileName(appname);
+//    return ShowResponseMessage(appname, description);
+//}
+
+TString WindowsPlatform::GetBundledJVMLibraryFileName(TString RuntimePath) {
+    TString result = FilePath::IncludeTrailingSeparater(RuntimePath) +
+        _T("jre\\bin\\jli.dll");
+
+    if (FilePath::FileExists(result) == false) {
+        result = FilePath::IncludeTrailingSeparater(RuntimePath) +
+            _T("bin\\jli.dll");
+    }
+
+    return result;
+}
+
+ISectionalPropertyContainer* WindowsPlatform::GetConfigFile(TString FileName) {
+    IniFile *result = new IniFile();
+
+    if (result->LoadFromFile(FileName) == false) {
+        // New property file format was not found, attempt to load old property file format.
+        Helpers::LoadOldConfigFile(FileName, result);
+    }
+
+    return result;
+}
+
+TString WindowsPlatform::GetModuleFileName() {
+    TString result;
+    DynamicBuffer<wchar_t> buffer(MAX_PATH);
+    ::GetModuleFileName(NULL, buffer.GetData(), static_cast<DWORD>(buffer.GetSize()));
+
+    while (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
+        buffer.Resize(buffer.GetSize() * 2);
+        ::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_PACKAGER_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;
+}
+
+void WindowsPlatform::reactivateAnotherInstance() {
+    if (singleInstanceProcessId == 0) {
+        printf("Unable to reactivate another instance, PID is undefined");
+        return;
+    }
+    EnumWindows(&enumWindows, (LPARAM)singleInstanceProcessId);
+}
+
+// returns true if another instance is already running.
+// if false, we need to continue regular launch.
+bool WindowsPlatform::CheckForSingleInstance(TString name) {
+    if (SingleInstance::getInstance(name)->IsAnotherInstanceRunning()) {
+        // read PID
+        DWORD pid = SingleInstance::getInstance(name)->readPid();
+        if (pid != 0) {
+            singleInstanceProcessId = pid;
+            return true;
+        }
+    } else {
+        // it is the first intance
+        // write pid and continue regular launch
+        SingleInstance::getInstance(name)->writePid(GetCurrentProcessId());
+    }
+    return false;
+}
+
+SingleInstance::SingleInstance(TString& name_): BUF_SIZE(256), _name(name_), _hMapFile(NULL), _pBuf(NULL) {
+    _mutex = CreateMutex(NULL, TRUE, name_.data());
+    _lastError = GetLastError();
+    _sharedMemoryName = _T("Local\\javapackager-") + _name;
+}
+
+SingleInstance::~SingleInstance() {
+    if (_pBuf != NULL) {
+        UnmapViewOfFile(_pBuf);
+        _pBuf = NULL;
+    }
+
+    if (_hMapFile != NULL) {
+        CloseHandle(_hMapFile);
+        _hMapFile = NULL;
+    }
+
+    if (_mutex != NULL) {
+        CloseHandle(_mutex);
+        _mutex = NULL;
+    }
+}
+
+bool SingleInstance::writePid(DWORD pid) {
+    _hMapFile = CreateFileMapping(
+                 INVALID_HANDLE_VALUE,
+                 NULL,
+                 PAGE_READWRITE,
+                 0,
+                 BUF_SIZE,
+                 _sharedMemoryName.data());
+
+    if (_hMapFile == NULL) {
+        return false;
+    }
+
+    _pBuf = (LPTSTR) MapViewOfFile(_hMapFile,
+                        FILE_MAP_ALL_ACCESS,
+                        0,
+                        0,
+                        BUF_SIZE);
+
+    if (_pBuf == NULL) {
+        CloseHandle(_hMapFile);
+        _hMapFile = NULL;
+        return false;
+    }
+
+    CopyMemory((PVOID)_pBuf, &pid, sizeof(DWORD));
+
+    return true;
+}
+
+DWORD SingleInstance::readPid() {
+    _hMapFile = OpenFileMapping(
+                   FILE_MAP_ALL_ACCESS,
+                   FALSE,
+                   _sharedMemoryName.data());
+
+    if (_hMapFile == NULL) {
+        return 0;
+    }
+
+   _pBuf = (LPTSTR) MapViewOfFile(_hMapFile,
+               FILE_MAP_ALL_ACCESS,
+               0,
+               0,
+               BUF_SIZE);
+
+    if (_pBuf == NULL) {
+        CloseHandle(_hMapFile);
+        _hMapFile = NULL;
+        return 0;
+    }
+
+    DWORD pid = 0;
+    CopyMemory(&pid, (PVOID)_pBuf,  sizeof(DWORD));
+
+    return pid;
+}
+
+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> WindowsPlatform::GetLibraryImports(const TString FileName) {
+ std::vector<TString> result;
+    WindowsLibrary library(FileName);
+    result = library.GetImports();
+ 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;
+}
+
+std::vector<TString> WindowsPlatform::FilterOutRuntimeDependenciesForPlatform(std::vector<TString> Imports) {
+ std::vector<TString> result;
+
+    Package& package = Package::GetInstance();
+    Macros& macros = Macros::GetInstance();
+    TString runtimeDir = macros.ExpandMacros(package.GetJVMRuntimeDirectory());
+    std::vector<TString> filelist = FilterList(Imports, std::wregex(_T("MSVCR.*.DLL"), std::regex_constants::icase));
+
+    for (std::vector<TString>::iterator it = filelist.begin(); it != filelist.end(); ++it) {
+        TString filename = *it;
+        TString msvcr100FileName = FilePath::IncludeTrailingSeparater(runtimeDir) + _T("jre\\bin\\") + filename;
+
+        if (FilePath::FileExists(msvcr100FileName) == true) {
+            result.push_back(msvcr100FileName);
+            break;
+        }
+        else {
+            msvcr100FileName = FilePath::IncludeTrailingSeparater(runtimeDir) + _T("bin\\") + filename;
+
+            if (FilePath::FileExists(msvcr100FileName) == true) {
+                result.push_back(msvcr100FileName);
+                break;
+            }
+        }
+    }
+
+ return result;
+}
+
+Process* WindowsPlatform::CreateProcess() {
+    return new WindowsProcess();
+}
+
+#ifdef DEBUG
+bool WindowsPlatform::IsNativeDebuggerPresent() {
+    bool result = false;
+
+    if (IsDebuggerPresent() == TRUE) {
+        result = true;
+    }
+
+    return result;
+}
+
+int WindowsPlatform::GetProcessID() {
+    int pid = GetProcessId(GetCurrentProcess());
+    return pid;
+}
+#endif //DEBUG
+
+//--------------------------------------------------------------------------------------------------
+
+WindowsJavaUserPreferences::WindowsJavaUserPreferences(void) : JavaUserPreferences() {
+}
+
+WindowsJavaUserPreferences::~WindowsJavaUserPreferences(void) {
+}
+
+// Java Preferences API encodes it's strings, so we need to match what Java does to work with Java.
+// CAVEAT: Java also does unicode encoding which this doesn't do yet. Should be sufficient for jvm args.
+// See WindowsPreferences.java toWindowsName()
+TString ConvertStringToJavaEcodedString(TString Value) {
+    TString result;
+    TCHAR* p = (TCHAR*)Value.c_str();
+    TCHAR c = *p;
+
+    while (c != 0) {
+        switch (c) {
+            case '\\':
+                result += _T("//");
+                break;
+
+            case '/':
+                result += '\\';
+                break;
+            default:
+                if ((c >= 'A') && (c <= 'Z')) {
+                    result += '/';
+                    result += c;
+                }
+                else
+                    result += c;
+                break;
+        }
+
+        p++;
+        c = *p;
+    }
+
+    return result;
+}
+
+// Java Preferences API encodes it's strings, so we need to match what Java does to work with Java.
+// CAVEAT: Java also does unicode encoding which this doesn't do yet. Should be sufficient for jvm args.
+// See WindowsPreferences.java toJavaName()
+TString ConvertJavaEcodedStringToString(TString Value) {
+    TString result;
+
+    for (size_t index = 0; index < Value.length(); index++) {
+        TCHAR c = Value[index];
+
+        switch (c) {
+            case '/':
+                if ((index + 1) < Value.length()) {
+                    index++;
+                    TCHAR nextc = Value[index];
+
+                    if (nextc >= 'A' && nextc <= 'Z') {
+                        result += nextc;
+                    }
+                    else if (nextc == '/') {
+                        result += '\\';
+                    }
+                }
+                break;
+            case '\\':
+                result += '/';
+                break;
+            default:
+                result += c;
+                break;
+        }
+    }
+
+    return result;
+}
+
+bool WindowsJavaUserPreferences::Load(TString Appid) {
+    bool result = false;
+    TString lappid = Helpers::ConvertIdToFilePath(Appid);
+    lappid = ConvertStringToJavaEcodedString(Appid);
+    TString registryKey = TString(_T("SOFTWARE\\JavaSoft\\Prefs\\")) + lappid + TString(_T("\\/J/V/M/User/Options"));
+    Registry registry(HKEY_CURRENT_USER);
+
+    if (registry.Open(registryKey) == true) {
+        std::list<TString> keys = registry.GetKeys();
+        OrderedMap<TString, TString> mapOfKeysAndValues;
+
+        for (std::list<TString>::const_iterator iterator = keys.begin(); iterator != keys.end(); iterator++) {
+            TString key = *iterator;
+            TString value = registry.ReadString(key);
+            key = ConvertJavaEcodedStringToString(key);
+            value = ConvertJavaEcodedStringToString(value);
+
+            if (key.empty() == false) {
+                mapOfKeysAndValues.Append(key, value);
+                result = true;
+            }
+        }
+
+        FMap = mapOfKeysAndValues;
+    }
+
+    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);
+    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();
+}
+
+#endif //WINDOWS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/WindowsPlatform.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+
+#ifdef WINDOWS
+
+#ifndef WINDOWSPLATFORM_H
+#define WINDOWSPLATFORM_H
+
+#include "GenericPlatform.h"
+#include "JavaUserPreferences.h"
+
+#include <Windows.h>
+
+
+// the class is used to create and detect single instance of user application
+class SingleInstance {
+private:
+    const int BUF_SIZE;
+
+    DWORD  _lastError;
+    HANDLE _mutex;
+    TString _name;
+    TString _sharedMemoryName;
+    HANDLE _hMapFile;
+    LPCTSTR _pBuf;
+
+    SingleInstance(): BUF_SIZE(0) {}
+
+    SingleInstance(TString& name_);
+
+public:
+    static SingleInstance* getInstance(TString& name) {
+        static SingleInstance* result = NULL;
+
+        if (result == NULL) {
+            result = new SingleInstance(name);
+        }
+
+        return result;
+    }
+
+    ~SingleInstance();
+
+    bool IsAnotherInstanceRunning() {
+        return (ERROR_ALREADY_EXISTS == _lastError);
+    }
+
+    bool writePid(DWORD pid);
+    DWORD readPid();
+};
+
+#pragma warning( push )
+#pragma warning( disable : 4250 ) // C4250 - 'class1' : inherits 'class2::member'
+class WindowsPlatform : virtual public Platform, GenericPlatform {
+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 MessageResponse ShowResponseMessage(TString description);
+
+    virtual void SetCurrentDirectory(TString Value);
+    virtual TString GetPackageRootDirectory();
+    virtual TString GetAppDataDirectory();
+    virtual TString GetBundledJVMLibraryFileName(TString RuntimePath);
+
+    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 std::vector<TString> GetLibraryImports(const TString FileName);
+    virtual std::vector<TString> FilterOutRuntimeDependenciesForPlatform(std::vector<TString> Imports);
+
+    virtual Process* CreateProcess();
+
+    virtual void reactivateAnotherInstance();
+    virtual bool IsMainThread();
+    virtual bool CheckForSingleInstance(TString Name);
+    virtual TPlatformNumber GetMemorySize();
+
+    virtual TString GetTempDirectory();
+
+#ifdef DEBUG
+    virtual bool IsNativeDebuggerPresent();
+    virtual int GetProcessID();
+#endif //DEBUG
+};
+#pragma warning( pop ) // C4250
+
+
+class WindowsJavaUserPreferences : public JavaUserPreferences {
+public:
+    WindowsJavaUserPreferences(void);
+    ~WindowsJavaUserPreferences(void);
+
+    virtual bool Load(TString Appid);
+};
+
+
+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
+
+#endif // WINDOWS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/share/native/library/common/main.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+#include "Platform.h"
+#include "PlatformString.h"
+#include "FilePath.h"
+#include "PropertyFile.h"
+#include "JavaVirtualMachine.h"
+#include "Package.h"
+#include "PlatformThread.h"
+#include "Macros.h"
+#include "Messages.h"
+
+
+#ifdef WINDOWS
+#include <Shellapi.h>
+#endif
+
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+
+/*
+This is the launcher program for application packaging on Windows, Mac and Linux.
+
+Basic approach:
+  - Launcher executable loads packager.dll/libpackager.dylib/libpackager.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 JVM with requested JVM settings (bundled client JVM if availble, server or installed JVM otherwise).
+  - Wait for JVM 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 JVM.
+    See CR 6316197 for more information.
+*/
+
+extern "C" {
+
+#ifdef WINDOWS
+    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
+        return true;
+    }
+
+    __declspec(dllexport)
+#endif //WINDOWS
+#ifdef LINUX
+    __attribute__((externally_visible,visibility("default")))
+#endif //LINUX
+    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;
+                }
+#ifdef DEBUG
+                // There is a compiler bug on Mac when overloading ShowResponseMessage.
+                else if (argument == _T("-nativedebug")) {
+                    if (platform.ShowResponseMessage(_T("Test"),
+                                                     TString(_T("Would you like to debug?\n\nProcessID: ")) +
+                                                     PlatformString(platform.GetProcessID()).toString()) == mrOK) {
+                        while (platform.IsNativeDebuggerPresent() == false) {
+                        }
+                    }
+                }
+#endif //DEBUG
+            }
+
+            // Package must be initialized after Platform is fully initialized.
+            Package& package = Package::GetInstance();
+            Macros::Initialize();
+            package.SetCommandLineArguments(argc, argv);
+            platform.SetCurrentDirectory(package.GetPackageAppDirectory());
+
+            if (package.CheckForSingleInstance()) {
+                // reactivate the first instance if the process Id is valid
+                platform.reactivateAnotherInstance();
+                if (package.GetArgs().size() > 0 && platform.GetSingleInstanceProcessId() != 0) {
+                    // if user specified args, try to pass them to the first instance
+                    return RunVM(SINGLE_INSTANCE_NOTIFICATION_LAUNCH);
+                }
+                return true;
+            }
+
+            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 FileNotFoundException(message);
+                            }
+                            break;
+                        }
+
+                    case cdsUninitialized: {
+                        // throw Exception(_T("Internal Error")); // VS2017
+                        platform.ShowMessage(_T("Internal Error"));
+                        break;
+                    }
+                }
+            }
+            // Run App
+            result = RunVM(USER_APP_LAUNCH);
+        }
+        catch (FileNotFoundException &e) {
+            platform.ShowMessage(e.GetMessage());
+        }
+
+        return result;
+    }
+
+#ifdef WINDOWS
+    __declspec(dllexport)
+#endif //WINDOWS
+#ifdef LINUX
+    __attribute__((externally_visible,visibility("default")))
+#endif //LINUX
+    void stop_launcher() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/unix/scripts/jpackager	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,103 @@
+#!/bin/bash
+#
+# Java Packager tool execution script for Linux and OS X.
+#
+
+# Default values.
+DEBUG=""
+MEMORY="-Xmx512M"
+JAVA_ARGS=""
+DEBUG_ARG="-J-Xdebug:";
+
+# Argument parsing.
+args=
+narg=1
+for i in "$@"; do
+    if [[ "$i" == "-J-Xmx"* ]]; then
+        ARGUMENT=${i:2}
+        MEMORY=${ARGUMENT}
+    elif [[ "$i" == ${DEBUG_ARG}* ]]; then
+        ADDRESS=${i:${#DEBUG_ARG}}
+        DEBUG="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=${ADDRESS}"
+    elif [[ "$i" == "-J-"* ]]; then
+        ARGUMENT=${i:2}
+        JAVA_ARGS="${JAVA_ARGS} ${ARGUMENT}"
+    else
+        args="$args \"$""{"$narg"}\""
+    fi
+    narg=`expr $narg + 1`
+done
+
+# resolve symlinks
+PRG=$0
+while [ -h "$PRG" ]; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
+    if expr "$link" : '^/' 2> /dev/null >/dev/null; then
+	PRG="$link"
+    else
+	PRG="`dirname "$PRG"`/$link"
+    fi
+done
+
+# detect Darwin and Cygwin environments
+darwin=false;
+cygwin=false;
+case "`uname`" in
+  Darwin*) darwin=true;
+           if [ -z "$JAVA_HOME" ] ; then
+               BIN_DIR=`dirname $PRG`
+               JAVA_HOME=`cd $BIN_DIR > /dev/null; pwd`/..
+           fi
+           ;;
+  CYGWIN*) cygwin=true;;
+esac
+
+JAVA_PACKAGER_PATH=$(cd $(dirname $0) ; pwd -P)
+JAVA_CMD="${JAVA_PACKAGER_PATH}/java"
+
+if [[ ! -f ${JAVA_CMD} ]]; then
+  if [ -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/javac" ] ; then
+      JAVA_CMD="$JAVA_HOME/bin/java"
+      export JAVA_HOME
+  else
+    JAVAC_CMD=`which javac 2> /dev/null `
+    while [ -h "$JAVAC_CMD" ]; do
+      ls=`ls -ld "$JAVAC_CMD"`
+      link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
+      if expr "$link" : '^/' 2> /dev/null >/dev/null; then
+        JAVAC_CMD="$link"
+      else
+        JAVAC_CMD="`dirname "$JAVAC_CMD"`/$link"
+      fi
+    done
+
+    BIN_DIR=`dirname "$JAVAC_CMD"`
+    JAVA_HOME=`dirname "$BIN_DIR"`
+    if [ "m$JAVA_HOME" != "m." ]; then
+      JAVA_CMD="$JAVA_HOME/bin/java"
+      export JAVA_HOME
+    else
+      unset JAVA_HOME
+      JAVA_CMD=`which java 2> /dev/null `
+      if [ -z "$JAVA_CMD" ]; then
+        JAVA_CMD="java"
+      fi
+    fi
+  fi
+fi
+
+if [ ! -x "$JAVA_CMD" ] ; then
+  echo 'Error: JAVA_HOME is not defined, cannot find "java" command.'
+  exit 1
+fi
+
+if $cygwin ; then
+    JAVA_CMD=`cygpath --unix "$JAVA_CMD"`
+fi
+
+# This is similar to "$@" except we had to strip out some arguments
+# that we don't want to be passed to the Java Packager.
+eval exec "$JAVA_CMD" ${DEBUG} ${MEMORY} ${JAVA_ARGS} \
+    -m jdk.packager/jdk.packager.Main $args
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/builders/windows/WindowsAppImageBuilder.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2015, 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.packager.internal.builders.windows;
+
+
+import jdk.packager.internal.BundlerParamInfo;
+import jdk.packager.internal.Log;
+import jdk.packager.internal.RelativeFileSet;
+import jdk.packager.internal.IOUtils;
+import jdk.packager.internal.StandardBundlerParam;
+import jdk.packager.internal.resources.windows.WinResources;
+import jdk.packager.internal.windows.WindowsBundlerParam;
+import jdk.packager.internal.builders.AbstractAppImageBuilder;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileInputStream;
+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.file.Files;
+import java.nio.file.Path;
+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.packager.internal.StandardBundlerParam.*;
+import jdk.packager.internal.windows.WindowsDefender;
+
+
+public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.builders.windows.WindowsAppImageBuilder");
+
+    private static final String MODULES_FILENAME =
+            "jdk/packager/internal/resources/windows/windows.jre.list";
+
+    protected static final String WINDOWS_BUNDLER_PREFIX =
+            BUNDLER_PREFIX + "windows" + File.separator;
+
+    private final static String EXECUTABLE_NAME = "WinLauncher.exe";
+    private final static String LIBRARY_NAME = "packager.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 ="javalogo_white_48.ico";
+
+    private static final String EXECUTABLE_PROPERTIES_TEMPLATE =
+            "WinLauncher.properties";
+
+    private final Path root;
+    private final Path appDir;
+    private final Path runtimeDir;
+    private final Path mdir;
+
+    private final Map<String, ? super Object> params;
+
+    public static final BundlerParamInfo<File> CONFIG_ROOT =
+            new WindowsBundlerParam<>(
+            I18N.getString("param.config-root.name"),
+            I18N.getString("param.config-root.description"),
+            "configRoot",
+            File.class,
+            params -> {
+                File imagesRoot =
+                        new File(BUILD_ROOT.fetchFrom(params), "windows");
+                imagesRoot.mkdirs();
+                return imagesRoot;
+            },
+            (s, p) -> null);
+
+    public static final BundlerParamInfo<Boolean> REBRAND_EXECUTABLE =
+            new WindowsBundlerParam<>(
+            I18N.getString("param.rebrand-executable.name"),
+            I18N.getString("param.rebrand-executable.description"),
+            "win.launcher.rebrand",
+            Boolean.class,
+            params -> Boolean.TRUE,
+            (s, p) -> Boolean.valueOf(s));
+
+    public static final BundlerParamInfo<File> ICON_ICO =
+            new StandardBundlerParam<>(
+            I18N.getString("param.icon-ico.name"),
+            I18N.getString("param.icon-ico.description"),
+            "icon.ico",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".ico")) {
+                    Log.info(MessageFormat.format(
+                            I18N.getString("message.icon-not-ico"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+
+
+    public WindowsAppImageBuilder(Map<String, Object> config, Path imageOutDir)
+            throws IOException {
+        super(config,
+                imageOutDir.resolve(APP_NAME.fetchFrom(config) + "/runtime"));
+
+        Objects.requireNonNull(imageOutDir);
+
+        this.params = config;
+
+        this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params));
+        this.appDir = root.resolve("app");
+        this.runtimeDir = root.resolve("runtime");
+        this.mdir = runtimeDir.resolve("lib");
+        Files.createDirectories(appDir);
+        Files.createDirectories(runtimeDir);
+    }
+
+    public WindowsAppImageBuilder(String jreName, Path imageOutDir)
+            throws IOException {
+        super(null, imageOutDir.resolve(jreName));
+
+        Objects.requireNonNull(imageOutDir);
+
+        this.params = null;
+        this.root = imageOutDir.resolve(jreName);
+        this.appDir = null;
+        this.runtimeDir = root;
+        this.mdir = runtimeDir.resolve("lib");
+        Files.createDirectories(runtimeDir);
+    }
+
+    private Path destFile(String dir, String filename) {
+        return runtimeDir.resolve(dir).resolve(filename);
+    }
+
+    private void writeEntry(InputStream in, Path dstFile) throws IOException {
+        Files.createDirectories(dstFile.getParent());
+        Files.copy(in, dstFile);
+    }
+
+    private void writeSymEntry(Path dstFile, Path target) throws IOException {
+        Files.createDirectories(dstFile.getParent());
+        Files.createLink(dstFile, target);
+    }
+
+    /**
+     * chmod ugo+x file
+     */
+    private void setExecutable(Path file) {
+        try {
+            Set<PosixFilePermission> perms =
+                Files.getPosixFilePermissions(file);
+            perms.add(PosixFilePermission.OWNER_EXECUTE);
+            perms.add(PosixFilePermission.GROUP_EXECUTE);
+            perms.add(PosixFilePermission.OTHERS_EXECUTE);
+            Files.setPosixFilePermissions(file, perms);
+        } catch (IOException ioe) {
+            throw new UncheckedIOException(ioe);
+        }
+    }
+
+    private static void createUtf8File(File file, String content)
+            throws IOException {
+        try (OutputStream fout = new FileOutputStream(file);
+             Writer output = new OutputStreamWriter(fout, "UTF-8")) {
+            output.write(content);
+        }
+    }
+
+    // This method is static for the sake of sharing with "installer" bundlers
+    // that may skip calls to validate/bundle in this class!
+    public static File getRootDir(File outDir, Map<String, ? super Object> p) {
+        return new File(outDir, APP_FS_NAME.fetchFrom(p));
+    }
+
+    public static String getLauncherName(Map<String, ? super Object> p) {
+        return APP_FS_NAME.fetchFrom(p) + ".exe";
+    }
+
+    public static String getLauncherCfgName(Map<String, ? super Object> p) {
+        return "app/" + APP_FS_NAME.fetchFrom(p) +".cfg";
+    }
+
+    private File getConfig_AppIcon(Map<String, ? super Object> params) {
+        return new File(getConfigRoot(params),
+                APP_FS_NAME.fetchFrom(params) + ".ico");
+    }
+
+    private File getConfig_ExecutableProperties(
+           Map<String, ? super Object> params) {
+        return new File(getConfigRoot(params),
+                APP_FS_NAME.fetchFrom(params) + ".properties");
+    }
+
+    File getConfigRoot(Map<String, ? super Object> params) {
+        return CONFIG_ROOT.fetchFrom(params);
+    }
+
+    protected void cleanupConfigFiles(Map<String, ? super Object> params) {
+        if (!StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            getConfig_AppIcon(params).delete();
+            getConfig_ExecutableProperties(params).delete();
+        }
+    }
+
+    @Override
+    public InputStream getResourceAsStream(String name) {
+        return WinResources.class.getResourceAsStream(name);
+    }
+
+    @Override
+    public void prepareApplicationFiles() throws IOException {
+        Map<String, ? super Object> originalParams = new HashMap<>(params);
+        File rootFile = root.toFile();
+        if (!rootFile.isDirectory() && !rootFile.mkdirs()) {
+            throw new RuntimeException(MessageFormat.format(I18N.getString(
+                "error.cannot-create-output-dir"), rootFile.getAbsolutePath()));
+        }
+        if (!rootFile.canWrite()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-write-to-output-dir"),
+                    rootFile.getAbsolutePath()));
+        }
+        try {
+            // create the .exe launchers
+            createLauncherForEntryPoint(params);
+
+            // copy the jars
+            copyApplication(params);
+
+            // copy in the needed libraries
+            try (InputStream is_lib = getResourceAsStream("packager.dll")) {
+                Files.copy(is_lib, root.resolve(LIBRARY_NAME));
+            }
+
+            copyMSVCDLLs();
+
+            // create the secondary launchers, if any
+            List<Map<String, ? super Object>> entryPoints = 
+                    StandardBundlerParam.SECONDARY_LAUNCHERS.fetchFrom(params);
+            for (Map<String, ? super Object> entryPoint : entryPoints) {
+                Map<String, ? super Object> tmp = new HashMap<>(originalParams);
+                tmp.putAll(entryPoint);
+                createLauncherForEntryPoint(tmp);
+            }
+
+        } catch (IOException ex) {
+            Log.info("Exception: "+ex);
+            Log.debug(ex);
+        } finally {
+
+            if (ECHO_MODE.fetchFrom(params)) {
+                Log.info(MessageFormat.format(I18N.getString(
+                        "message.config-save-location"),
+                        getConfigRoot(params).getAbsolutePath()));
+            } else {
+                cleanupConfigFiles(params);
+            }
+        }
+    }
+
+    @Override
+    public void prepareServerJreFiles() 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, root.resolve((p.toFile().getName())));
+                    } catch (IOException e) {
+                        ioe.set(e);
+                    } 
+                });
+        }
+
+        IOException e = ioe.get();
+        if (e != null) {
+            throw e;
+        }
+    }
+
+    // TODO: do we still need this?
+    private boolean copyMSVCDLLs(String VS_VER) throws IOException {
+        final InputStream REDIST_MSVCR_URL =
+                WinResources.class.getResourceAsStream(
+                REDIST_MSVCR.replaceAll("VS_VER", VS_VER));
+        final InputStream REDIST_MSVCP_URL =
+                WinResources.class.getResourceAsStream(
+                REDIST_MSVCP.replaceAll("VS_VER", VS_VER));
+
+        if (REDIST_MSVCR_URL != null && REDIST_MSVCP_URL != null) {
+            Files.copy(
+                    REDIST_MSVCR_URL,
+                    root.resolve(REDIST_MSVCR.replaceAll("VS_VER", VS_VER)));
+            Files.copy(
+                    REDIST_MSVCP_URL,
+                    root.resolve(REDIST_MSVCP.replaceAll("VS_VER", VS_VER)));
+            return true;
+        }
+
+        return false;
+    }
+
+    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.info("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
+        data.put("COMMENTS", "");
+        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("LEGAL_TRADEMARK", "");
+        data.put("ORIGINAL_FILENAME", getLauncherName(params));
+        data.put("PRIVATE_BUILD", "");
+        validateValueAndPut(data, "PRODUCT_NAME", APP_NAME, params);
+        validateValueAndPut(data, "PRODUCT_VERSION", VERSION, params);
+        data.put("SPECIAL_BUILD", "");
+
+        Writer w = new BufferedWriter(
+                new FileWriter(getConfig_ExecutableProperties(params)));
+        String content = preprocessTextResource(WINDOWS_BUNDLER_PREFIX
+                + getConfig_ExecutableProperties(params).getName(),
+                I18N.getString("resource.executable-properties-template"),
+                EXECUTABLE_PROPERTIES_TEMPLATE, data,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        w.write(content);
+        w.close();
+    }
+
+    private void createLauncherForEntryPoint(
+            Map<String, ? super Object> p) throws IOException {
+
+        File launcherIcon = ICON_ICO.fetchFrom(p);
+        File icon = launcherIcon != null ?
+                launcherIcon : ICON_ICO.fetchFrom(params);
+        File iconTarget = getConfig_AppIcon(p);
+
+        InputStream in = locateResource(
+               "package/windows/" + APP_NAME.fetchFrom(params) + ".ico",
+                "icon",
+                TEMPLATE_APP_ICON,
+                icon,
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        Files.copy(in, iconTarget.toPath());
+
+        writeCfgFile(p, root.resolve(
+                getLauncherCfgName(p)).toFile(), "$APPDIR\\runtime");
+
+        prepareExecutableProperties(p);
+
+        // Copy executable root folder
+        Path executableFile = root.resolve(getLauncherName(p));
+        try (InputStream is_launcher =
+                getResourceAsStream("papplauncher.exe")) {
+            writeEntry(is_launcher, executableFile);
+        }
+        
+        File launcher = executableFile.toFile();
+        launcher.setWritable(true, true);
+
+        // Update branding of EXE file
+        if (REBRAND_EXECUTABLE.fetchFrom(p)) {
+            File tool = new File(
+                System.getProperty("java.home") + "\\bin\\jpackager.exe");
+
+            // Run tool on launcher file to change the icon and the metadata.
+            try {
+                if (WindowsDefender.isThereAPotentialWindowsDefenderIssue()) {
+                    Log.info(MessageFormat.format(I18N.getString(
+                            "message.potential.windows.defender.issue"),
+                            WindowsDefender.getUserTempDirectory()));
+                }
+
+                launcher.setWritable(true);
+
+                if (iconTarget.exists()) {
+                    ProcessBuilder pb = new ProcessBuilder(
+                            tool.getAbsolutePath(),
+                            "--icon-swap",
+                            iconTarget.getAbsolutePath(),
+                            launcher.getAbsolutePath());
+                    IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+                }
+
+                File executableProperties = getConfig_ExecutableProperties(p);
+
+                if (executableProperties.exists()) {
+                    ProcessBuilder pb = new ProcessBuilder(
+                            tool.getAbsolutePath(),
+                            "--version-swap",
+                            executableProperties.getAbsolutePath(),
+                            launcher.getAbsolutePath());
+                    IOUtils.exec(pb, ECHO_MODE.fetchFrom(p));
+                }
+            }
+            finally {
+                executableFile.toFile().setReadOnly();
+            }
+        }
+
+        Files.copy(iconTarget.toPath(),
+                root.resolve(APP_NAME.fetchFrom(p) + ".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);
+            }
+        }
+    }
+
+    @Override
+    protected String getCacheLocation(Map<String, ? super Object> params) {
+        return "$CACHEDIR/";
+    }
+
+    @Override
+    public String getPlatformSpecificModulesFile() {
+        return MODULES_FILENAME;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/builders/windows/WindowsAppImageBuilder.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,16 @@
+param.rebrand-executable.name = Rebrand Launcher
+param.rebrand-executable.description = Update the launcher with the application icon and update ownership information.
+
+param.icon-ico.name=.ico Icon
+param.icon-ico.description=Icon for the application, in ICO format.
+
+param.config-root.name=
+param.config-root.description=
+
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+
+message.config-save-location=Config files are saved to {0}. Use them to customize package.
+message.potential.windows.defender.issue=Warning: Windows Defender may prevent the Java Packager from functioning. If there is an issue, it can be addressed by either disabling realtime monitoring, or adding an exclusion for the directory "{0}".
+
+resource.executable-properties-template=Template for creating executable properties file.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/builders/windows/WindowsAppImageBuilder_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,16 @@
+param.rebrand-executable.name = \u30E9\u30F3\u30C1\u30E3\u306E\u30EA\u30D6\u30E9\u30F3\u30C9
+param.rebrand-executable.description = \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A2\u30A4\u30B3\u30F3\u3092\u542B\u3080\u30E9\u30F3\u30C1\u30E3\u304A\u3088\u3073\u6240\u6709\u8005\u60C5\u5831\u3092\u66F4\u65B0\u3057\u307E\u3059\u3002
+
+param.icon-ico.name=.ico\u30A2\u30A4\u30B3\u30F3
+param.icon-ico.description=ICO\u5F62\u5F0F\u3067\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30A2\u30A4\u30B3\u30F3\u3002
+
+param.config-root.name=
+param.config-root.description=
+
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+
+message.config-save-location=\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C{0}\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B\u306B\u306F\u3053\u308C\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+message.potential.windows.defender.issue=\u8B66\u544A: Windows Defender\u304C\u539F\u56E0\u3067Java\u30D1\u30C3\u30B1\u30FC\u30B8\u30E3\u304C\u6A5F\u80FD\u3057\u306A\u3044\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\u554F\u984C\u304C\u767A\u751F\u3057\u305F\u5834\u5408\u306F\u3001\u30EA\u30A2\u30EB\u30BF\u30A4\u30E0\u30FB\u30E2\u30CB\u30BF\u30EA\u30F3\u30B0\u3092\u7121\u52B9\u306B\u3059\u308B\u304B\u3001\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA"{0}"\u306E\u9664\u5916\u3092\u8FFD\u52A0\u3059\u308B\u3053\u3068\u306B\u3088\u308A\u3001\u554F\u984C\u306B\u5BFE\u51E6\u3067\u304D\u307E\u3059\u3002
+
+resource.executable-properties-template=\u5B9F\u884C\u53EF\u80FD\u306A\u30D7\u30ED\u30D1\u30C6\u30A3\u30FB\u30D5\u30A1\u30A4\u30EB\u4F5C\u6210\u7528\u306E\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/builders/windows/WindowsAppImageBuilder_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,16 @@
+param.rebrand-executable.name = \u66F4\u6539\u542F\u52A8\u7A0B\u5E8F\u54C1\u724C
+param.rebrand-executable.description = \u4F7F\u7528\u5E94\u7528\u7A0B\u5E8F\u56FE\u6807\u66F4\u65B0\u542F\u52A8\u7A0B\u5E8F\u5E76\u66F4\u65B0\u6240\u6709\u6743\u4FE1\u606F\u3002
+
+param.icon-ico.name=.ico \u56FE\u6807
+param.icon-ico.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u56FE\u6807, \u91C7\u7528 ICO \u683C\u5F0F\u3002
+
+param.config-root.name=
+param.config-root.description=
+
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+
+message.config-save-location=\u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58\u5230 {0}\u3002\u4F7F\u7528\u8FD9\u4E9B\u914D\u7F6E\u6587\u4EF6\u53EF\u5B9A\u5236\u7A0B\u5E8F\u5305\u3002
+message.potential.windows.defender.issue=\u8B66\u544A: Windows Defender \u53EF\u80FD\u4F1A\u963B\u6B62 Java \u6253\u5305\u7A0B\u5E8F\u6B63\u5E38\u5DE5\u4F5C\u3002\u5982\u679C\u5B58\u5728\u95EE\u9898, \u53EF\u4EE5\u901A\u8FC7\u7981\u7528\u5B9E\u65F6\u76D1\u89C6\u6216\u8005\u4E3A\u76EE\u5F55 "{0}" \u6DFB\u52A0\u6392\u9664\u9879\u8FDB\u884C\u89E3\u51B3\u3002
+
+resource.executable-properties-template=\u7528\u4E8E\u521B\u5EFA\u53EF\u6267\u884C\u5C5E\u6027\u6587\u4EF6\u7684\u6A21\u677F\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WinAppBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,32 @@
+bundler.name=Windows Application Image
+bundler.description=A Directory based image of a windows Application with an optionally co-bundled JRE.  Used as a base for the Installer bundlers
+
+param.config-root.name=
+param.config-root.description=
+
+param.raw-executable-url.name=Launcher URL
+param.raw-executable-url.description=Override the packager default launcher with a custom launcher.
+
+param.rebrand-executable.name=Rebrand Launcher
+param.rebrand-executable.description=Update the launcher with the application icon and update ownership information.
+
+param.icon-ico.name=.ico Icon
+param.icon-ico.description=Icon for the application, in ICO format.
+
+resource.application-icon=application icon
+
+error.parameters-null=Parameters map is null.
+error.parameters-null.advice=Pass in a non-null parameters map.
+error.no-windows-resources=This copy of the JDK does not support Windows.
+error.no-windows-resources.advice=Please use the Oracle JDK for Windows.
+error.bit-architecture-mismatch=Bit architecture mismatch between FX SDK and JRE runtime.
+error.bit-architecture-mismatch.advice=Make sure to use JRE runtime with correct bit architecture.
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+
+message.creating-app-bundle=Creating app bundle\: {0} in {1}
+message.result-dir=Result application bundle\: {0}
+message.config-save-location=Config files are saved to {0}. Use them to customize package.
+message.disable-bit-architecture-check=Disabled check for bit architecture mismatch.
+message.jvm-user-arg-is-null=WARNING\: a jvmuserarg has a null name or value
+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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WinAppBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,32 @@
+bundler.name=Windows\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8
+bundler.description=\u30AA\u30D7\u30B7\u30E7\u30F3\u3067JRE\u304C\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u3066\u3044\u308BWindows\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30FB\u30D9\u30FC\u30B9\u306E\u30A4\u30E1\u30FC\u30B8\u3002\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FB\u30D0\u30F3\u30C9\u30E9\u306E\u30D9\u30FC\u30B9\u3068\u3057\u3066\u4F7F\u7528\u3055\u308C\u307E\u3059
+
+param.config-root.name=
+param.config-root.description=
+
+param.raw-executable-url.name=\u30E9\u30F3\u30C1\u30E3URL
+param.raw-executable-url.description=\u30D1\u30C3\u30B1\u30FC\u30B8\u30E3\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30E9\u30F3\u30C1\u30E3\u3092\u30AB\u30B9\u30BF\u30E0\u30FB\u30E9\u30F3\u30C1\u30E3\u3067\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u3059\u3002
+
+param.rebrand-executable.name=\u30E9\u30F3\u30C1\u30E3\u306E\u30EA\u30D6\u30E9\u30F3\u30C9
+param.rebrand-executable.description=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A2\u30A4\u30B3\u30F3\u3092\u542B\u3080\u30E9\u30F3\u30C1\u30E3\u304A\u3088\u3073\u6240\u6709\u8005\u60C5\u5831\u3092\u66F4\u65B0\u3057\u307E\u3059\u3002
+
+param.icon-ico.name=.ico\u30A2\u30A4\u30B3\u30F3
+param.icon-ico.description=ICO\u5F62\u5F0F\u3067\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30A2\u30A4\u30B3\u30F3\u3002
+
+resource.application-icon=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A2\u30A4\u30B3\u30F3
+
+error.parameters-null=\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u304Cnull\u3067\u3059\u3002
+error.parameters-null.advice=\u975Enull\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u3067\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.no-windows-resources=\u3053\u306EJDK\u306E\u30B3\u30D4\u30FC\u3067\u306F\u3001Windows\u306F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002
+error.no-windows-resources.advice=Oracle JDK for Windows\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.bit-architecture-mismatch=FX SDK\u3068JRE\u30E9\u30F3\u30BF\u30A4\u30E0\u9593\u306E\u30D3\u30C3\u30C8\u30FB\u30A2\u30FC\u30AD\u30C6\u30AF\u30C1\u30E3\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002
+error.bit-architecture-mismatch.advice=\u6B63\u3057\u3044\u30D3\u30C3\u30C8\u30FB\u30A2\u30FC\u30AD\u30C6\u30AF\u30C1\u30E3\u3092\u6301\u3064JRE\u30E9\u30F3\u30BF\u30A4\u30E0\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+
+message.creating-app-bundle=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059: {1}\u5185\u306E{0}
+message.result-dir=\u7D50\u679C\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30F3\u30C9\u30EB: {0}
+message.config-save-location=\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C{0}\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B\u306B\u306F\u3053\u308C\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+message.disable-bit-architecture-check=\u30D3\u30C3\u30C8\u30FB\u30A2\u30FC\u30AD\u30C6\u30AF\u30C1\u30E3\u306E\u4E0D\u4E00\u81F4\u30C1\u30A7\u30C3\u30AF\u304C\u7121\u52B9\u306B\u306A\u3063\u3066\u3044\u307E\u3059\u3002
+message.jvm-user-arg-is-null=\u8B66\u544A: jvmuserarg\u306Bnull\u306E\u540D\u524D\u307E\u305F\u306F\u5024\u304C\u3042\u308A\u307E\u3059
+message.icon-not-ico=\u6307\u5B9A\u3057\u305F\u30A2\u30A4\u30B3\u30F3"{0}"\u306FICO\u30D5\u30A1\u30A4\u30EB\u3067\u306F\u306A\u304F\u3001\u4F7F\u7528\u3055\u308C\u307E\u305B\u3093\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3\u304C\u305D\u306E\u4F4D\u7F6E\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WinAppBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,32 @@
+bundler.name=Windows \u5E94\u7528\u7A0B\u5E8F\u6620\u50CF
+bundler.description=\u4E00\u4E2A\u57FA\u4E8E\u76EE\u5F55\u7684 Windows \u5E94\u7528\u7A0B\u5E8F\u6620\u50CF, \u53EF\u4EE5\u9009\u62E9\u6027\u5730\u5E26\u6709\u5171\u540C\u6253\u5305\u7684 JRE\u3002\u7528\u4F5C\u5B89\u88C5\u7A0B\u5E8F\u6253\u5305\u7A0B\u5E8F\u7684\u57FA\u7840
+
+param.config-root.name=
+param.config-root.description=
+
+param.raw-executable-url.name=\u542F\u52A8\u7A0B\u5E8F URL
+param.raw-executable-url.description=\u4F7F\u7528\u5B9A\u5236\u542F\u52A8\u7A0B\u5E8F\u8986\u76D6\u6253\u5305\u7A0B\u5E8F\u9ED8\u8BA4\u542F\u52A8\u7A0B\u5E8F\u3002
+
+param.rebrand-executable.name=\u66F4\u6539\u542F\u52A8\u7A0B\u5E8F\u54C1\u724C
+param.rebrand-executable.description=\u4F7F\u7528\u5E94\u7528\u7A0B\u5E8F\u56FE\u6807\u66F4\u65B0\u542F\u52A8\u7A0B\u5E8F\u5E76\u66F4\u65B0\u6240\u6709\u6743\u4FE1\u606F\u3002
+
+param.icon-ico.name=.ico \u56FE\u6807
+param.icon-ico.description=\u5E94\u7528\u7A0B\u5E8F\u7684\u56FE\u6807, \u91C7\u7528 ICO \u683C\u5F0F\u3002
+
+resource.application-icon=\u5E94\u7528\u7A0B\u5E8F\u56FE\u6807
+
+error.parameters-null=\u53C2\u6570\u6620\u5C04\u4E3A\u7A7A\u503C\u3002
+error.parameters-null.advice=\u8BF7\u4F20\u5165\u975E\u7A7A\u53C2\u6570\u6620\u5C04\u3002
+error.no-windows-resources=\u6B64 JDK \u7684\u526F\u672C\u4E0D\u652F\u6301 Windows\u3002
+error.no-windows-resources.advice=\u8BF7\u4F7F\u7528 Oracle JDK for Windows\u3002
+error.bit-architecture-mismatch=FX SDK \u4E0E JRE \u8FD0\u884C\u65F6\u4E4B\u95F4\u7684\u4F4D\u4F53\u7CFB\u7ED3\u6784\u4E0D\u5339\u914D\u3002
+error.bit-architecture-mismatch.advice=\u8BF7\u786E\u4FDD\u4F7F\u7528\u5E26\u6709\u6B63\u786E\u4F4D\u4F53\u7CFB\u7ED3\u6784\u7684 JRE \u8FD0\u884C\u65F6\u3002
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+
+message.creating-app-bundle=\u6B63\u5728 {1} \u4E2D\u521B\u5EFA\u5E94\u7528\u7A0B\u5E8F\u5305 {0}
+message.result-dir=\u751F\u6210\u7684\u5E94\u7528\u7A0B\u5E8F\u5305: {0}
+message.config-save-location=\u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58\u5230 {0}\u3002\u4F7F\u7528\u8FD9\u4E9B\u914D\u7F6E\u6587\u4EF6\u53EF\u5B9A\u5236\u7A0B\u5E8F\u5305\u3002
+message.disable-bit-architecture-check=\u5DF2\u7981\u7528\u4F4D\u4F53\u7CFB\u7ED3\u6784\u4E0D\u5339\u914D\u68C0\u67E5\u3002
+message.jvm-user-arg-is-null=\u8B66\u544A: jvmuserarg \u7684\u540D\u79F0\u6216\u503C\u4E3A\u7A7A\u503C
+message.icon-not-ico=\u6307\u5B9A\u7684\u56FE\u6807 "{0}" \u4E0D\u662F ICO \u6587\u4EF6, \u4E0D\u4F1A\u4F7F\u7528\u3002\u5C06\u4F7F\u7528\u9ED8\u8BA4\u56FE\u6807\u4EE3\u66FF\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WinLauncher.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,12 @@
+Comments=COMMENTS
+CompanyName=COMPANY_NAME	
+FileDescription=FILE_DESCRIPTION
+FileVersion=FILE_VERSION
+InternalName=INTERNAL_NAME
+LegalCopyright=LEGAL_COPYRIGHT
+LegalTrademarks=LEGAL_TRADEMARK
+OriginalFilename=ORIGINAL_FILENAME
+PrivateBuild=PRIVATE_BUILD
+ProductName=PRODUCT_NAME
+ProductVersion=PRODUCT_VERSION
+SpecialBuild=SPECIAL_BUILD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WinMsiBundler.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,81 @@
+bundler.name=MSI Installer
+bundler.description=Microsoft Windows MSI Installer, via WiX.
+
+param.system-wide.name=System Wide
+param.system-wide.description=Should this application attempt to install itself system wide, or only for each user?  Null means use the system default.
+
+param.app-bundler.name=
+param.app-bundler.description=
+
+param.service-bundler.name=
+param.service-bundler.description=
+
+param.can-use-wix36.name=
+param.can-use-wix36.description=
+
+param.out-dir.name=
+param.out-dir.description=
+
+param.config-root.name=
+param.config-root.description=
+
+param.image-dir.name=
+param.image-dir.description=
+
+param.app-dir.name=
+param.app-dir.description=
+
+param.menu-shortcut-hint.name=Menu Hint
+param.menu-shortcut-hint.description=If the bundler can add the application to the system menu, should it?
+
+param.desktop-shortcut-hint.name=Shortcut Hint
+param.desktop-shortcut-hint.description=If the bundler can create desktop shortcuts, should it make one?
+
+param.upgrade-uuid.name=Upgrade UUID
+param.upgrade-uuid.description=The UUID associated with upgrades for this package.
+
+param.product-version.name=Product Version
+param.product-version.description=The version of the application as seen by Windows and MSI, of the form "1.2.3"
+
+param.candle-path.name=WiX candle.exe location
+param.candle-path.description=File path to candle.exe from the WiX toolset.
+
+param.light-path.name=WiX light.exe location
+param.light-path.description=File path to light.exe from the WiX toolset.
+
+resource.post-install-script=script to run after application image is populated
+resource.wix-config-file=WiX config file
+
+error.parameters-null=Parameters map is null.
+error.parameters-null.advice=Pass in a non-null parameters map.
+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 http\://wix.sf.net 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: http\://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.cannot-walk-directory=Can not walk [{0}] - it is not a valid directory
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+error.too-many-content-types-for-file-association=More than one MIME types was specified for File Association number {0}.
+error.too-many-content-types-for-file-association.advice=For Linux Bundling specify one and only one MIME type for each file association.
+error.license-missing=can not find license file {0}.
+error.license-missing.advice=include license file {0} in the --files argument.
+
+
+message.tool-version=Detected [{0}] version [{1}]
+message.running-wsh-script=Running WSH script on application image [{0}]
+message.wrong-tool-version=Detected [{0}] version {1} but version {2} is required.
+message.use-wix36-features=WiX 3.6 detected. Enabling advanced cleanup action.
+message.version-string-too-many-components=Version sting may have up to 3 components - major.minor.build .
+message.debug-working-directory=Kept working directory for debug\: {0}
+message.config-save-location=Config files are saved to {0}. Use them to customize package.
+message.generated-product-guid=Generated product GUID\: {0}
+message.preparing-msi-config=Preparing MSI config\: {0}
+message.generating-msi=Generating MSI\: {0}
+message.one-shortcut-required=At least one type of shortcut is required. Enabling menu shortcut.
+message.light-file-string=WiX light tool set to {0}
+message.candle-file-string=WiX candle tool set to {0}
+message.creating-association-with-null-extension=Creating association with null extension.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WinMsiBundler_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,72 @@
+bundler.name=MSI\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9
+bundler.description=WiX\u3092\u4F7F\u7528\u3057\u305FMicrosoft Windows MSI\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u3002
+
+param.system-wide.name=\u30B7\u30B9\u30C6\u30E0\u5168\u4F53
+param.system-wide.description=\u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306F\u3001\u305D\u308C\u81EA\u4F53\u3092\u30B7\u30B9\u30C6\u30E0\u5168\u4F53\u306B\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u307E\u3059\u304B\u3001\u307E\u305F\u306F\u5404\u30E6\u30FC\u30B6\u30FC\u306B\u5BFE\u3057\u3066\u306E\u307F\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u307E\u3059\u304B\u3002Null\u306F\u30B7\u30B9\u30C6\u30E0\u30FB\u30C7\u30D5\u30A9\u30EB\u30C8\u3092\u4F7F\u7528\u3059\u308B\u3053\u3068\u3092\u610F\u5473\u3057\u307E\u3059\u3002
+
+param.app-bundler.name=
+param.app-bundler.description=
+
+param.service-bundler.name=
+param.service-bundler.description=
+
+param.can-use-wix36.name=
+param.can-use-wix36.description=
+
+param.out-dir.name=
+param.out-dir.description=
+
+param.config-root.name=
+param.config-root.description=
+
+param.image-dir.name=
+param.image-dir.description=
+
+param.app-dir.name=
+param.app-dir.description=
+
+param.upgrade-uuid.name=\u30A2\u30C3\u30D7\u30B0\u30EC\u30FC\u30C9UUID
+param.upgrade-uuid.description=\u3053\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u30A2\u30C3\u30D7\u30B0\u30EC\u30FC\u30C9\u306B\u95A2\u9023\u4ED8\u3051\u3089\u308C\u3066\u3044\u308BUUID\u3002
+
+param.product-version.name=\u88FD\u54C1\u30D0\u30FC\u30B8\u30E7\u30F3
+param.product-version.description=Windows\u304A\u3088\u3073MSI\u306B\u8868\u793A\u3055\u308C\u308B\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u30D0\u30FC\u30B8\u30E7\u30F3(\u5F62\u5F0F\u306F"1.2.3")
+
+param.candle-path.name=WiX candle.exe\u306E\u5834\u6240
+param.candle-path.description=WiX\u30C4\u30FC\u30EB\u30BB\u30C3\u30C8\u304B\u3089\u306Ecandle.exe\u3078\u306E\u30D5\u30A1\u30A4\u30EB\u30FB\u30D1\u30B9\u3002
+
+param.light-path.name=WiX light.exe\u306E\u5834\u6240
+param.light-path.description=WiX\u30C4\u30FC\u30EB\u30BB\u30C3\u30C8\u304B\u3089\u306Elight.exe\u3078\u306E\u30D5\u30A1\u30A4\u30EB\u30FB\u30D1\u30B9\u3002
+
+resource.post-install-script=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8\u3092\u79FB\u5165\u3057\u305F\u5F8C\u306B\u5B9F\u884C\u3059\u308B\u30B9\u30AF\u30EA\u30D7\u30C8
+resource.wix-config-file=WiX\u69CB\u6210\u30D5\u30A1\u30A4\u30EB
+
+error.parameters-null=\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u304Cnull\u3067\u3059\u3002
+error.parameters-null.advice=\u975Enull\u30D1\u30E9\u30E1\u30FC\u30BF\u30FB\u30DE\u30C3\u30D7\u3067\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+error.no-wix-tools=WiX\u30C4\u30FC\u30EB(light.exe\u3001candle.exe)\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002
+error.no-wix-tools.advice=WiX 3.0\u4EE5\u964D\u3092http://wix.sf.net\u304B\u3089\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3057\u3001PATH\u306B\u8FFD\u52A0\u3057\u307E\u3059\u3002
+error.version-string-wrong-format=\u30D0\u30FC\u30B8\u30E7\u30F3\u6587\u5B57\u5217\u306FMSI\u898F\u5247[{0}]\u3068\u4E92\u63DB\u6027\u304C\u3042\u308A\u307E\u305B\u3093\u3002
+error.version-string-wrong-format.advice=\u30D0\u30F3\u30C9\u30E9\u5F15\u6570"{0}"\u3092\u6B21\u306E\u898F\u5247\u306B\u5F93\u3063\u3066\u8A2D\u5B9A\u3057\u307E\u3059: http://msdn.microsoft.com/en-us/library/aa370859%28v=VS.85%29.aspx
+error.version-string-major-out-of-range=\u30E1\u30B8\u30E3\u30FC\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u306F\u7BC4\u56F2[0, 255]\u5185\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
+error.version-string-build-out-of-range=\u30D0\u30FC\u30B8\u30E7\u30F3\u306E\u30D3\u30EB\u30C9\u90E8\u5206\u306F\u7BC4\u56F2[0, 65535]\u5185\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
+error.version-string-minor-out-of-range=\u30DE\u30A4\u30CA\u30FC\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u306F\u7BC4\u56F2[0, 255]\u5185\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
+error.version-string-part-not-number=\u30D0\u30FC\u30B8\u30E7\u30F3\u30FB\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u306Eint\u3078\u306E\u5909\u63DB\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002
+error.cannot-walk-directory=[{0}]\u3067\u79FB\u52D5\u3067\u304D\u307E\u305B\u3093 - \u6709\u52B9\u306A\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3067\u306F\u3042\u308A\u307E\u305B\u3093
+error.cannot-create-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3002
+error.cannot-write-to-output-dir=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u306F\u66F8\u8FBC\u307F\u4E0D\u53EF\u3067\u3059\u3002
+error.too-many-content-types-for-file-association=\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u756A\u53F7{0}\u306B\u8907\u6570\u306EMIME\u30BF\u30A4\u30D7\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F\u3002
+error.too-many-content-types-for-file-association.advice=Linux\u30D0\u30F3\u30C9\u30EB\u306E\u5834\u5408\u3001\u5404\u30D5\u30A1\u30A4\u30EB\u30FB\u30A2\u30BD\u30B7\u30A8\u30FC\u30B7\u30E7\u30F3\u306BMIME\u30BF\u30A4\u30D7\u30921\u3064\u3060\u3051\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002
+
+message.tool-version=[{0}]\u30D0\u30FC\u30B8\u30E7\u30F3[{1}]\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F
+message.running-wsh-script=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8[{0}]\u3067WSH\u30B9\u30AF\u30EA\u30D7\u30C8\u3092\u5B9F\u884C\u3057\u3066\u3044\u307E\u3059
+message.wrong-tool-version=[{0}]\u30D0\u30FC\u30B8\u30E7\u30F3{1}\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F\u304C\u3001\u30D0\u30FC\u30B8\u30E7\u30F3{2}\u304C\u5FC5\u8981\u3067\u3059\u3002
+message.use-wix36-features=WiX 3.6\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F\u3002\u62E1\u5F35\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u30FB\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u5316\u3057\u3066\u3044\u307E\u3059\u3002
+message.version-string-too-many-components=\u30D0\u30FC\u30B8\u30E7\u30F3\u6587\u5B57\u5217\u306B\u306F\u3001\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u30923\u3064(\u30E1\u30B8\u30E3\u30FC.\u30DE\u30A4\u30CA\u30FC.\u30D3\u30EB\u30C9)\u307E\u3067\u542B\u3081\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002
+message.debug-working-directory=\u30C7\u30D0\u30C3\u30B0\u306E\u4F5C\u696D\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u4FDD\u6301\u3055\u308C\u307E\u3057\u305F: {0}
+message.config-save-location=\u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C{0}\u306B\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA\u3059\u308B\u306B\u306F\u3053\u308C\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
+message.generated-product-guid=\u88FD\u54C1GUID\u3092\u751F\u6210\u3057\u307E\u3057\u305F: {0}
+message.preparing-msi-config=MSI\u69CB\u6210\u3092\u6E96\u5099\u3057\u3066\u3044\u307E\u3059: {0}
+message.generating-msi=MSI\u3092\u751F\u6210\u3057\u3066\u3044\u307E\u3059: {0}
+message.one-shortcut-required=\u5C11\u306A\u304F\u3068\u30821\u3064\u306E\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u30FB\u30BF\u30A4\u30D7\u304C\u5FC5\u8981\u3067\u3059\u3002\u30E1\u30CB\u30E5\u30FC\u30FB\u30B7\u30E7\u30FC\u30C8\u30AB\u30C3\u30C8\u3092\u6709\u52B9\u5316\u3057\u3066\u3044\u307E\u3059\u3002
+message.light-file-string=WiX light\u30C4\u30FC\u30EB\u304C{0}\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3057\u305F
+message.candle-file-string=WiX candle\u30C4\u30FC\u30EB\u304C{0}\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3057\u305F
+message.creating-association-with-null-extension=null\u62E1\u5F35\u5B50\u3068\u306E\u95A2\u9023\u4ED8\u3051\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WinMsiBundler_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,72 @@
+bundler.name=MSI \u5B89\u88C5\u7A0B\u5E8F
+bundler.description=Microsoft Windows MSI \u5B89\u88C5\u7A0B\u5E8F, \u901A\u8FC7 WiX\u3002
+
+param.system-wide.name=\u7CFB\u7EDF\u8303\u56F4
+param.system-wide.description=\u6B64\u5E94\u7528\u7A0B\u5E8F\u662F\u5E94\u5C1D\u8BD5\u5728\u7CFB\u7EDF\u8303\u56F4\u5185\u5B89\u88C5, \u8FD8\u662F\u4EC5\u4E3A\u6BCF\u4E2A\u7528\u6237\u5B89\u88C5? \u7A7A\u503C\u8868\u793A\u4F7F\u7528\u7CFB\u7EDF\u9ED8\u8BA4\u503C\u3002
+
+param.app-bundler.name=
+param.app-bundler.description=
+
+param.service-bundler.name=
+param.service-bundler.description=
+
+param.can-use-wix36.name=
+param.can-use-wix36.description=
+
+param.out-dir.name=
+param.out-dir.description=
+
+param.config-root.name=
+param.config-root.description=
+
+param.image-dir.name=
+param.image-dir.description=
+
+param.app-dir.name=
+param.app-dir.description=
+
+param.upgrade-uuid.name=\u5347\u7EA7 UUID
+param.upgrade-uuid.description=\u4E0E\u6B64\u7A0B\u5E8F\u5305\u7684\u5347\u7EA7\u5173\u8054\u7684 UUID\u3002
+
+param.product-version.name=\u4EA7\u54C1\u7248\u672C
+param.product-version.description=\u5411 Windows \u548C MSI \u663E\u793A\u7684\u5E94\u7528\u7A0B\u5E8F\u7684\u7248\u672C, \u5F62\u5F0F\u4E3A "1.2.3"
+
+param.candle-path.name=WiX candle.exe \u4F4D\u7F6E
+param.candle-path.description=WiX \u5DE5\u5177\u96C6\u4E2D candle.exe \u7684\u6587\u4EF6\u8DEF\u5F84\u3002
+
+param.light-path.name=WiX light.exe \u4F4D\u7F6E
+param.light-path.description=WiX \u5DE5\u5177\u96C6\u4E2D light.exe \u7684\u6587\u4EF6\u8DEF\u5F84\u3002
+
+resource.post-install-script=\u8981\u5728\u586B\u5145\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF\u4E4B\u540E\u8FD0\u884C\u7684\u811A\u672C
+resource.wix-config-file=WiX \u914D\u7F6E\u6587\u4EF6
+
+error.parameters-null=\u53C2\u6570\u6620\u5C04\u4E3A\u7A7A\u503C\u3002
+error.parameters-null.advice=\u8BF7\u4F20\u5165\u975E\u7A7A\u53C2\u6570\u6620\u5C04\u3002
+error.no-wix-tools=\u627E\u4E0D\u5230 WiX \u5DE5\u5177 (light.exe, candle.exe)\u3002
+error.no-wix-tools.advice=\u4ECE http://wix.sf.net \u4E0B\u8F7D WiX 3.0 \u6216\u66F4\u9AD8\u7248\u672C, \u7136\u540E\u5C06\u5176\u6DFB\u52A0\u5230 PATH\u3002
+error.version-string-wrong-format=\u7248\u672C\u5B57\u7B26\u4E32\u4E0D\u7B26\u5408 MSI \u89C4\u5219 [{0}]\u3002
+error.version-string-wrong-format.advice=\u6839\u636E\u4EE5\u4E0B\u89C4\u5219\u8BBE\u7F6E\u6253\u5305\u7A0B\u5E8F\u53C2\u6570 "{0}": http://msdn.microsoft.com/en-us/library/aa370859%28v=VS.85%29.aspx
+error.version-string-major-out-of-range=\u4E3B\u7248\u672C\u5FC5\u987B\u4F4D\u4E8E [0, 255] \u8303\u56F4\u4E2D
+error.version-string-build-out-of-range=\u7248\u672C\u7684\u5DE5\u4F5C\u7248\u672C\u90E8\u5206\u5FC5\u987B\u4F4D\u4E8E [0, 65535] \u8303\u56F4\u4E2D
+error.version-string-minor-out-of-range=\u6B21\u7248\u672C\u5FC5\u987B\u4F4D\u4E8E [0, 255] \u8303\u56F4\u4E2D
+error.version-string-part-not-number=\u65E0\u6CD5\u5C06\u7248\u672C\u7EC4\u6210\u90E8\u5206\u8F6C\u6362\u4E3A\u6574\u6570\u3002
+error.cannot-walk-directory=\u65E0\u6CD5\u904D\u5386 [{0}] - \u5B83\u4E0D\u662F\u6709\u6548\u7684\u76EE\u5F55
+error.cannot-create-output-dir=\u65E0\u6CD5\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55 {0}\u3002
+error.cannot-write-to-output-dir=\u8F93\u51FA\u76EE\u5F55 {0} \u4E0D\u53EF\u5199\u3002
+error.too-many-content-types-for-file-association=\u4E3A\u6587\u4EF6\u5173\u8054\u53F7{0}\u6307\u5B9A\u4E86\u591A\u4E2A MIME \u7C7B\u578B\u3002
+error.too-many-content-types-for-file-association.advice=\u5BF9\u4E8E Linux \u6253\u5305, \u8BF7\u4E3A\u6BCF\u4E2A\u6587\u4EF6\u5173\u8054\u6307\u5B9A\u4E00\u4E2A\u4E14\u4EC5\u6307\u5B9A\u4E00\u4E2A MIME \u7C7B\u578B\u3002
+
+message.tool-version=\u68C0\u6D4B\u5230 [{0}] \u7248\u672C [{1}]
+message.running-wsh-script=\u5728\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF [{0}] \u4E0A\u8FD0\u884C WSH \u811A\u672C
+message.wrong-tool-version=\u68C0\u6D4B\u5230 [{0}] \u7248\u672C {1}, \u4F46\u9700\u8981\u7248\u672C {2}\u3002
+message.use-wix36-features=\u68C0\u6D4B\u5230 WiX 3.6\u3002\u6B63\u5728\u542F\u7528\u9AD8\u7EA7\u6E05\u9664\u64CD\u4F5C\u3002
+message.version-string-too-many-components=\u7248\u672C\u5B57\u7B26\u4E32\u6700\u591A\u53EF\u4EE5\u5177\u6709 3 \u4E2A\u7EC4\u6210\u90E8\u5206 - major.minor.build\u3002
+message.debug-working-directory=\u7528\u4E8E\u8C03\u8BD5\u7684\u5DF2\u4FDD\u7559\u5DE5\u4F5C\u76EE\u5F55: {0}
+message.config-save-location=\u914D\u7F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58\u5230 {0}\u3002\u4F7F\u7528\u8FD9\u4E9B\u914D\u7F6E\u6587\u4EF6\u53EF\u5B9A\u5236\u7A0B\u5E8F\u5305\u3002
+message.generated-product-guid=\u5DF2\u751F\u6210\u4EA7\u54C1 GUID: {0}
+message.preparing-msi-config=\u6B63\u5728\u51C6\u5907 MSI \u914D\u7F6E: {0}
+message.generating-msi=\u6B63\u5728\u751F\u6210 MSI: {0}
+message.one-shortcut-required=\u81F3\u5C11\u9700\u8981\u4E00\u79CD\u7C7B\u578B\u7684\u5FEB\u6377\u65B9\u5F0F\u3002\u6B63\u5728\u542F\u7528\u83DC\u5355\u5FEB\u6377\u65B9\u5F0F\u3002
+message.light-file-string=WiX light \u5DE5\u5177\u8BBE\u7F6E\u4E3A{0}
+message.candle-file-string=WiX candle \u5DE5\u5177\u8BBE\u7F6E\u4E3A{0}
+message.creating-association-with-null-extension=\u6B63\u5728\u4F7F\u7528\u7A7A\u6269\u5C55\u540D\u521B\u5EFA\u5173\u8054\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WinResources.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011, 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.packager.internal.resources.windows;
+
+public class WinResources {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WindowsBundlerParam.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,21 @@
+param.menu-group.name=Menu Group
+param.menu-group.description=The Start Menu group this application should be placed in
+param.menu-group.default=Unknown
+
+param.64-bit.name=64-bit
+param.64-bit.description=Prepare the bundles for 64 bit windows.
+
+param.runtime-64-bit.name=runtime 64-bit
+param.runtime-64-bit.description=Embedded JRE runtime is 64-bit, used to detect bit architecture mismatches.
+
+param.installer-name.name=Installer Name
+param.installer-name.description=The filename of the generated installer without the file type extension.  Default is <App Name>-<Version>.
+
+param.registry-name.name=Registry Name
+param.registry-name.description=The name of the application for registry references.  Default is the Application Name with only alphanumerics, dots, and dashes (no whitespace).
+
+param.runtime.name=JRE
+param.runtime.description=The Java Runtime to co-bundle.  The default value is the current JRE running the bundler.  A value of null will cause no JRE to be co-bundled and the system JRE will be used to launch the application.
+
+param.installdir-chooser.name=Install Directory Chooser
+param.installdir-chooser.description=Adds a dialog to let the user choose a directory where the product will be installed.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WindowsBundlerParam_ja.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,21 @@
+param.menu-group.name=\u30E1\u30CB\u30E5\u30FC\u30FB\u30B0\u30EB\u30FC\u30D7
+param.menu-group.description=\u3053\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u914D\u7F6E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u8D77\u52D5\u30E1\u30CB\u30E5\u30FC\u30FB\u30B0\u30EB\u30FC\u30D7
+param.menu-group.default=\u4E0D\u660E
+
+param.64-bit.name=64\u30D3\u30C3\u30C8
+param.64-bit.description=64\u30D3\u30C3\u30C8\u306EWindows\u7528\u306E\u30D0\u30F3\u30C9\u30EB\u3092\u6E96\u5099\u3057\u307E\u3059\u3002
+
+param.runtime-64-bit.name=\u30E9\u30F3\u30BF\u30A4\u30E064\u30D3\u30C3\u30C8
+param.runtime-64-bit.description=\u57CB\u8FBC\u307FJRE\u30E9\u30F3\u30BF\u30A4\u30E0\u306F64\u30D3\u30C3\u30C8\u3067\u3001\u30D3\u30C3\u30C8\u30FB\u30A2\u30FC\u30AD\u30C6\u30AF\u30C1\u30E3\u306E\u4E0D\u4E00\u81F4\u306E\u691C\u51FA\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+
+param.installer-name.name=\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u540D
+param.installer-name.description=\u30D5\u30A1\u30A4\u30EB\u30FB\u30BF\u30A4\u30D7\u62E1\u5F35\u5B50\u306A\u3057\u306E\u751F\u6210\u3055\u308C\u305F\u30A4\u30F3\u30B9\u30C8\uFF0D\u30E9\u306E\u30D5\u30A1\u30A4\u30EB\u540D\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F<App Name>-<Version>\u3067\u3059\u3002
+
+param.registry-name.name=\u30EC\u30B8\u30B9\u30C8\u30EA\u540D
+param.registry-name.description=\u30EC\u30B8\u30B9\u30C8\u30EA\u53C2\u7167\u7528\u306E\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u540D\u524D\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F\u3001\u82F1\u6570\u5B57\u3001\u30C9\u30C3\u30C8\u304A\u3088\u3073\u30C0\u30C3\u30B7\u30E5(\u7A7A\u767D\u306A\u3057)\u306E\u307F\u3092\u4F7F\u7528\u3057\u305F\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D\u3067\u3059\u3002
+
+param.runtime.name=JRE
+param.runtime.description=\u30D0\u30F3\u30C9\u30EB\u3059\u308BJava\u30E9\u30F3\u30BF\u30A4\u30E0\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u306F\u3001\u30D0\u30F3\u30C9\u30E9\u3092\u5B9F\u884C\u3057\u3066\u3044\u308B\u73FE\u5728\u306EJRE\u3067\u3059\u3002\u5024\u304Cnull\u306E\u5834\u5408\u3001JRE\u306F\u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305A\u3001\u30B7\u30B9\u30C6\u30E0\u306EJRE\u304C\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u8D77\u52D5\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002
+
+param.installdir-chooser.name=\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u9078\u629E
+param.installdir-chooser.description=\u30E6\u30FC\u30B6\u30FC\u304C\u88FD\u54C1\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3059\u308B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u9078\u629E\u3059\u308B\u305F\u3081\u306E\u30C0\u30A4\u30A2\u30ED\u30B0\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/WindowsBundlerParam_zh_CN.properties	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,21 @@
+param.menu-group.name=\u83DC\u5355\u7EC4
+param.menu-group.description=\u5E94\u5C06\u6B64\u5E94\u7528\u7A0B\u5E8F\u653E\u7F6E\u5230\u7684\u5F00\u59CB\u83DC\u5355\u7EC4
+param.menu-group.default=\u672A\u77E5
+
+param.64-bit.name=64 \u4F4D
+param.64-bit.description=\u51C6\u5907\u9002\u7528\u4E8E 64 \u4F4D Windows \u7684\u5305\u3002
+
+param.runtime-64-bit.name=\u8FD0\u884C\u65F6 64 \u4F4D
+param.runtime-64-bit.description=\u5D4C\u5165\u5F0F JRE \u8FD0\u884C\u65F6\u4E3A 64 \u4F4D, \u7528\u4E8E\u68C0\u6D4B\u4F4D\u4F53\u7CFB\u7ED3\u6784\u4E0D\u5339\u914D\u60C5\u51B5\u3002
+
+param.installer-name.name=\u5B89\u88C5\u7A0B\u5E8F\u540D\u79F0
+param.installer-name.description=\u6240\u751F\u6210\u5B89\u88C5\u7A0B\u5E8F\u4E0D\u5E26\u6587\u4EF6\u7C7B\u578B\u6269\u5C55\u540D\u7684\u6587\u4EF6\u540D\u3002\u9ED8\u8BA4\u503C\u4E3A <\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0>-<\u7248\u672C>\u3002
+
+param.registry-name.name=\u6CE8\u518C\u8868\u540D\u79F0
+param.registry-name.description=\u7528\u4E8E\u6CE8\u518C\u8868\u5F15\u7528\u7684\u5E94\u7528\u7A0B\u5E8F\u7684\u540D\u79F0\u3002\u9ED8\u8BA4\u503C\u4E3A\u53EA\u5305\u542B\u5B57\u6BCD\u6570\u5B57, \u70B9\u548C\u77ED\u5212\u7EBF (\u65E0\u7A7A\u683C) \u7684\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0\u3002
+
+param.runtime.name=JRE
+param.runtime.description=\u8981\u5171\u540C\u6253\u5305\u7684 Java \u8FD0\u884C\u65F6\u3002\u9ED8\u8BA4\u503C\u4E3A\u8FD0\u884C\u6253\u5305\u7A0B\u5E8F\u7684\u5F53\u524D JRE\u3002\u503C\u4E3A\u7A7A\u503C\u5C06\u5BFC\u81F4\u4E0D\u4F1A\u5171\u540C\u6253\u5305\u4EFB\u4F55 JRE, \u5E76\u4E14\u5C06\u4F7F\u7528\u7CFB\u7EDF JRE \u6765\u542F\u52A8\u5E94\u7528\u7A0B\u5E8F\u3002
+
+param.installdir-chooser.name=\u5B89\u88C5\u76EE\u5F55\u9009\u62E9\u5668
+param.installdir-chooser.description=\u6DFB\u52A0\u5BF9\u8BDD\u6846\u4EE5\u5141\u8BB8\u7528\u6237\u9009\u62E9\u5C06\u5728\u5176\u4E2D\u5B89\u88C5\u4EA7\u54C1\u7684\u76EE\u5F55\u3002
Binary file src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/icon_inno_setup.bmp has changed
Binary file src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/javalogo_white_16.ico has changed
Binary file src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/javalogo_white_32.ico has changed
Binary file src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/javalogo_white_48.ico has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/template.server.jre.wxs	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
+     xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
+    <Product Id="PRODUCT_GUID" Name="APPLICATION_NAME" 
+             Language="1033" Version="APPLICATION_VERSION"
+             Manufacturer="APPLICATION_VENDOR" 
+             UpgradeCode="PRODUCT_UPGRADE_GUID">
+        <Package Description="APPLICATION_DESCRIPTION" Comments="None"
+                 InstallerVersion="200" Compressed="yes"
+                 InstallScope="INSTALL_SCOPE" Platform="PLATFORM"/>
+        <Media Id="1" Cabinet="simple.cab" EmbedCab="yes" />
+
+        <!-- We use RemoveFolderEx to ensure application folder is fully 
+             removed on uninstall. Including files created outside of MSI
+             after application had been installed (e.g. on AU or user state).
+             
+             Hovewer, RemoveFolderEx is only available in WiX 3.6, 
+             we will comment it out if we running older WiX.
+
+             RemoveFolderEx requires that we "remember" the path for uninstall.
+             Read the path value and set the APPLICATIONFOLDER property with the value.
+        -->
+        <Property Id="APPLICATIONFOLDER">
+            <RegistrySearch Key="SOFTWARE\APPLICATION_VENDOR\APPLICATION_NAME" 
+                            Root="REGISTRY_ROOT" Type="raw" 
+                            Id="APPLICATIONFOLDER_REGSEARCH" Name="Path" />
+        </Property>
+        <DirectoryRef Id="APPLICATIONFOLDER">
+            <Component Id="CleanupMainApplicationFolder" Guid="*" Win64="WIN64">
+                <RegistryValue Root="REGISTRY_ROOT"
+                                   Key="SOFTWARE\APPLICATION_VENDOR\APPLICATION_NAME"
+                                   Name="Path" Type="string" Value="[APPLICATIONFOLDER]"
+                                   KeyPath="yes" />
+                <!-- We need to use APPLICATIONFOLDER variable here or RemoveFolderEx
+                     will not remove on "install". But only if WiX 3.6 is used. -->
+                WIX36_ONLY_START     
+                  <util:RemoveFolderEx On="uninstall" Property="APPLICATIONFOLDER" />
+                WIX36_ONLY_END
+            </Component>
+        </DirectoryRef>        
+        <?include bundle.wxi ?>
+UI_BLOCK
+    </Product>
+</Wix>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/template.wxs	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
+     xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
+    <Product Id="PRODUCT_GUID" Name="APPLICATION_NAME" 
+             Language="1033" Version="APPLICATION_VERSION"
+             Manufacturer="APPLICATION_VENDOR" 
+             UpgradeCode="PRODUCT_UPGRADE_GUID">
+        <Package Description="APPLICATION_DESCRIPTION" Comments="None"
+                 InstallerVersion="200" Compressed="yes"
+                 InstallScope="INSTALL_SCOPE" Platform="PLATFORM"/>
+        <Media Id="1" Cabinet="simple.cab" EmbedCab="yes" />
+
+        <!-- We use RemoveFolderEx to ensure application folder is fully 
+             removed on uninstall. Including files created outside of MSI
+             after application had been installed (e.g. on AU or user state).
+             
+             Hovewer, RemoveFolderEx is only available in WiX 3.6, 
+             we will comment it out if we running older WiX.
+
+             RemoveFolderEx requires that we "remember" the path for uninstall.
+             Read the path value and set the APPLICATIONFOLDER property with the value.
+        -->
+        <Property Id="APPLICATIONFOLDER">
+            <RegistrySearch Key="SOFTWARE\APPLICATION_VENDOR\APPLICATION_NAME" 
+                            Root="REGISTRY_ROOT" Type="raw" 
+                            Id="APPLICATIONFOLDER_REGSEARCH" Name="Path" />
+        </Property>
+        <DirectoryRef Id="APPLICATIONFOLDER">
+            <Component Id="CleanupMainApplicationFolder" Guid="*" Win64="WIN64">
+                <RegistryValue Root="REGISTRY_ROOT"
+                                   Key="SOFTWARE\APPLICATION_VENDOR\APPLICATION_NAME"
+                                   Name="Path" Type="string" Value="[APPLICATIONFOLDER]"
+                                   KeyPath="yes" />
+                <!-- We need to use APPLICATIONFOLDER variable here or RemoveFolderEx
+                     will not remove on "install". But only if WiX 3.6 is used. -->
+                WIX36_ONLY_START     
+                  <util:RemoveFolderEx On="uninstall" Property="APPLICATIONFOLDER" />
+                WIX36_ONLY_END
+            </Component>
+        </DirectoryRef>        
+        <?include bundle.wxi ?>
+UI_BLOCK
+        <Icon Id="DesktopIcon.exe" SourceFile="APPLICATION_ICON" />
+        <Icon Id="StartMenuIcon.exe" SourceFile="APPLICATION_ICON" />
+SECONDARY_LAUNCHER_ICONS
+    </Product>
+</Wix>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/resources/windows/windows.jre.list	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,3 @@
+; This file contains Windows-specific modules.
+
+jdk.crypto.mscapi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/windows/WinAppBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.windows;
+
+import jdk.packager.internal.AbstractImageBundler;
+import jdk.packager.internal.BundlerParamInfo;
+import jdk.packager.internal.ConfigException;
+import jdk.packager.internal.IOUtils;
+import jdk.packager.internal.Log;
+import jdk.packager.internal.Platform;
+import jdk.packager.internal.StandardBundlerParam;
+import jdk.packager.internal.UnsupportedPlatformException;
+import jdk.packager.internal.builders.windows.WindowsAppImageBuilder;
+import jdk.packager.internal.resources.windows.WinResources;
+
+import jdk.packager.internal.JLinkBundlerHelper;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.ResourceBundle;
+import jdk.packager.internal.Arguments;
+
+import static jdk.packager.internal.windows.WindowsBundlerParam.*;
+import jdk.packager.internal.builders.AbstractAppImageBuilder;
+
+public class WinAppBundler extends AbstractImageBundler {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.windows.WinAppBundler");
+
+    public static final BundlerParamInfo<File> ICON_ICO =
+            new StandardBundlerParam<>(
+            I18N.getString("param.icon-ico.name"),
+            I18N.getString("param.icon-ico.description"),
+            "icon.ico",
+            File.class,
+            params -> {
+                File f = ICON.fetchFrom(params);
+                if (f != null && !f.getName().toLowerCase().endsWith(".ico")) {
+                    Log.info(MessageFormat.format(
+                            I18N.getString("message.icon-not-ico"), f));
+                    return null;
+                }
+                return f;
+            },
+            (s, p) -> new File(s));
+
+    public WinAppBundler() {
+        super();
+        baseResourceLoader = WinResources.class;
+    }
+
+    public final static String WIN_BUNDLER_PREFIX =
+            BUNDLER_PREFIX + "windows/";
+
+    @Override
+    public boolean validate(Map<String, ? super Object> params)
+            throws UnsupportedPlatformException, ConfigException {
+        try {
+            if (params == null) throw new ConfigException(
+                    I18N.getString("error.parameters-null"),
+                    I18N.getString("error.parameters-null.advice"));
+
+            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"
+    boolean doValidate(Map<String, ? super Object> p)
+            throws UnsupportedPlatformException, ConfigException {
+        if (Platform.getPlatform() != Platform.WINDOWS) {
+            throw new UnsupportedPlatformException();
+        }
+
+        imageBundleValidation(p);
+
+        if (StandardBundlerParam.getPredefinedAppImage(p) != null) {
+            return true;
+        }
+
+        // Make sure that jpackager.exe exists.
+        File tool = new File(
+                System.getProperty("java.home") + "\\bin\\jpackager.exe");
+
+        if (!tool.exists()) {
+            throw new ConfigException(
+                    I18N.getString("error.no-windows-resources"),
+                    I18N.getString("error.no-windows-resources.advice"));
+        }
+
+        // validate runtime bit-architectire
+        testRuntimeBitArchitecture(p);
+
+        return true;
+    }
+
+    private static void testRuntimeBitArchitecture(
+            Map<String, ? super Object> params) throws ConfigException {
+        if ("true".equalsIgnoreCase(System.getProperty(
+                "fxpackager.disableBitArchitectureMismatchCheck"))) {
+            Log.debug(I18N.getString("message.disable-bit-architecture-check"));
+            return;
+        }
+
+        if ((BIT_ARCH_64.fetchFrom(params) !=
+                BIT_ARCH_64_RUNTIME.fetchFrom(params))) {
+            throw new ConfigException(
+                    I18N.getString("error.bit-architecture-mismatch"),
+                    I18N.getString("error.bit-architecture-mismatch.advice"));
+        }
+    }
+
+    // it is static for the sake of sharing with "Exe" bundles
+    // that may skip calls to validate/bundle in this class!
+    private static File getRootDir(File outDir, Map<String, ? super Object> p) {
+        return new File(outDir, APP_NAME.fetchFrom(p));
+    }
+
+    public static String getLauncherName(Map<String, ? super Object> p) {
+        return APP_NAME.fetchFrom(p) +".exe";
+    }
+
+    public static String getLauncherCfgName(Map<String, ? super Object> p) {
+        return "app\\" + APP_NAME.fetchFrom(p) +".cfg";
+    }
+
+    public boolean bundle(Map<String, ? super Object> p, File outputDirectory) {
+        return doBundle(p, outputDirectory, false) != null;
+    }
+    
+    private File createRoot(Map<String, ? super Object> p,
+            File outputDirectory, boolean dependentTask) throws IOException {
+        if (!outputDirectory.isDirectory() && !outputDirectory.mkdirs()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-create-output-dir"),
+                    outputDirectory.getAbsolutePath()));
+        }
+        if (!outputDirectory.canWrite()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-write-to-output-dir"),
+                    outputDirectory.getAbsolutePath()));
+        }
+        if (!dependentTask) {
+            Log.info(MessageFormat.format(
+                    I18N.getString("message.creating-app-bundle"),
+                    APP_NAME.fetchFrom(p), outputDirectory.getAbsolutePath()));
+        }
+
+        // Create directory structure
+        File rootDirectory = getRootDir(outputDirectory, p);
+        IOUtils.deleteRecursive(rootDirectory);
+        rootDirectory.mkdirs();
+
+        if (!p.containsKey(JLinkBundlerHelper.JLINK_BUILDER.getID())) {
+            p.put(JLinkBundlerHelper.JLINK_BUILDER.getID(),
+                    "windowsapp-image-builder");
+        }
+
+        return rootDirectory;
+    }
+
+    File doBundle(Map<String, ? super Object> p,
+                File outputDirectory, boolean dependentTask) {
+        if (Arguments.CREATE_JRE_INSTALLER.fetchFrom(p)) {
+            return doJreBundle(p, outputDirectory, dependentTask);
+        } else {
+            return doAppBundle(p, outputDirectory, dependentTask);
+        }
+    }
+
+    File doJreBundle(Map<String, ? super Object> p,
+            File outputDirectory, boolean dependentTask) {
+        try {
+            File rootDirectory = createRoot(p, outputDirectory, dependentTask);
+            AbstractAppImageBuilder appBuilder = new WindowsAppImageBuilder(
+                    APP_NAME.fetchFrom(p),
+                    outputDirectory.toPath());
+            File predefined = PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
+            if (predefined == null ) {
+                JLinkBundlerHelper.generateServerJre(p, appBuilder);
+            } else {
+                return predefined;
+            }
+            return rootDirectory;
+        } catch (IOException ex) {
+            Log.info("Exception: "+ex);
+            Log.debug(ex);
+            return null;
+        } catch (Exception ex) {
+            Log.info("Exception: "+ex);
+            Log.debug(ex);
+            return null;
+        }
+    }
+
+    File doAppBundle(Map<String, ? super Object> p,
+            File outputDirectory, boolean dependentTask) {
+        try {
+            File rootDirectory =
+                    createRoot(p, outputDirectory, dependentTask);
+            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.info(MessageFormat.format(
+                        I18N.getString("message.result-dir"),
+                        outputDirectory.getAbsolutePath()));
+            }
+            return rootDirectory;
+        } catch (IOException ex) {
+            Log.info(ex.toString());
+            Log.verbose(ex);
+            return null;
+        } catch (Exception ex) {
+            Log.info("Exception: "+ex);
+            Log.debug(ex);
+            return null;
+        }
+    }
+
+    private static final String RUNTIME_AUTO_DETECT = ".runtime.autodetect";
+
+    public static void extractFlagsFromRuntime(
+            Map<String, ? super Object> params) {
+        if (params.containsKey(".runtime.autodetect")) return;
+
+        params.put(RUNTIME_AUTO_DETECT, "attempted");
+
+        String commandline;
+        File runtimePath = JLinkBundlerHelper.getJDKHome(params).toFile();
+        File launcherPath = new File(runtimePath, "bin\\java.exe");
+
+        ProcessBuilder pb =
+                 new ProcessBuilder(launcherPath.getAbsolutePath(), "-version");
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            try (PrintStream pout = new PrintStream(baos)) {
+                IOUtils.exec(pb, Log.isDebug(), true, pout);
+            }
+
+            commandline = baos.toString();
+        } catch (IOException e) {
+            e.printStackTrace();
+            params.put(RUNTIME_AUTO_DETECT, "failed");
+            return;
+        }
+
+        AbstractImageBundler.extractFlagsFromVersion(params, commandline);
+        params.put(RUNTIME_AUTO_DETECT, "succeeded");
+    }
+
+    @Override
+    public String getName() {
+        return I18N.getString("bundler.name");
+    }
+
+    @Override
+    public String getDescription() {
+        return I18N.getString("bundler.description");
+    }
+
+    @Override
+    public String getID() {
+        return "windows.app";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "IMAGE";
+    }
+
+    @Override
+    public Collection<BundlerParamInfo<?>> getBundleParameters() {
+        return getAppBundleParameters();
+    }
+
+    public static Collection<BundlerParamInfo<?>> getAppBundleParameters() {
+        return Arrays.asList(
+                APP_NAME,
+                APP_RESOURCES,
+                ARGUMENTS,
+                CLASSPATH,
+                ICON_ICO,
+                JVM_OPTIONS,
+                JVM_PROPERTIES,
+                MAIN_CLASS,
+                MAIN_JAR,
+                PREFERENCES_ID,
+                PRELOADER_CLASS,
+                USER_JVM_OPTIONS,
+                VERSION,
+                VERBOSE
+            );
+    }
+
+    @Override
+    public File execute(
+            Map<String, ? super Object> params, File outputParentDir) {
+        return doBundle(params, outputParentDir, false);
+    }
+    
+    @Override    
+    public boolean supported() {
+        return (Platform.getPlatform() == Platform.WINDOWS);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/windows/WinMsiBundler.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,1267 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.windows;
+
+import jdk.packager.internal.*;
+import jdk.packager.internal.ConfigException;
+import jdk.packager.internal.Arguments;
+import jdk.packager.internal.UnsupportedPlatformException;
+import jdk.packager.internal.resources.windows.WinResources;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static jdk.packager.internal.windows.WindowsBundlerParam.*;
+
+public class WinMsiBundler  extends AbstractBundler {
+
+    private static final ResourceBundle I18N =
+            ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.windows.WinMsiBundler");
+
+    public static final BundlerParamInfo<WinAppBundler> APP_BUNDLER =
+            new WindowsBundlerParam<>(
+            I18N.getString("param.app-bundler.name"),
+            I18N.getString("param.app-bundler.description"),
+            "win.app.bundler",
+            WinAppBundler.class,
+            params -> new WinAppBundler(),
+            null);
+
+    public static final BundlerParamInfo<Boolean> CAN_USE_WIX36 =
+            new WindowsBundlerParam<>(
+            I18N.getString("param.can-use-wix36.name"),
+            I18N.getString("param.can-use-wix36.description"),
+            "win.msi.canUseWix36",
+            Boolean.class,
+            params -> false,
+            (s, p) -> Boolean.valueOf(s));
+
+    public static final BundlerParamInfo<File> CONFIG_ROOT =
+            new WindowsBundlerParam<>(
+            I18N.getString("param.config-root.name"),
+            I18N.getString("param.config-root.description"),
+            "configRoot",
+            File.class,
+            params -> {
+                File imagesRoot =
+                        new File(BUILD_ROOT.fetchFrom(params), "windows");
+                imagesRoot.mkdirs();
+                return imagesRoot;
+            },
+            (s, p) -> null);
+
+    public static final BundlerParamInfo<File> MSI_IMAGE_DIR =
+            new WindowsBundlerParam<>(
+            I18N.getString("param.image-dir.name"),
+            I18N.getString("param.image-dir.description"),
+            "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<>(
+            I18N.getString("param.app-dir.name"),
+            I18N.getString("param.app-dir.description"),
+            "win.app.image",
+            File.class,
+            null,
+            (s, p) -> null);
+
+    public static final StandardBundlerParam<Boolean> MSI_SYSTEM_WIDE  =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.system-wide.name"),
+                    I18N.getString("param.system-wide.description"),
+                    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<>(
+                    I18N.getString("param.product-version.name"),
+                    I18N.getString("param.product-version.description"),
+                    "win.msi.productVersion",
+                    String.class,
+                    VERSION::fetchFrom,
+                    (s, p) -> s
+            );
+
+    public static final BundlerParamInfo<UUID> UPGRADE_UUID =
+            new WindowsBundlerParam<>(
+            I18N.getString("param.upgrade-uuid.name"),
+            I18N.getString("param.upgrade-uuid.description"),
+            Arguments.CLIOptions.WIN_MSI_UPGRADE_UUID.getId(),
+            UUID.class,
+            params -> UUID.randomUUID(), // TODO check to see
+                    // if identifier is a valid UUID during default
+            (s, p) -> UUID.fromString(s));
+
+    private static final String TOOL_CANDLE = "candle.exe";
+    private static final String TOOL_LIGHT = "light.exe";
+    // autodetect just v3.7, v3.8, 3.9, 3.10 and 3.11
+    private static final String AUTODETECT_DIRS =
+            ";C:\\Program Files (x86)\\WiX Toolset v3.11\\bin;"
+            + "C:\\Program Files\\WiX Toolset v3.11\\bin;"
+            + "C:\\Program Files (x86)\\WiX Toolset v3.10\\bin;"
+            + "C:\\Program Files\\WiX Toolset v3.10\\bin;"
+            + "C:\\Program Files (x86)\\WiX Toolset v3.9\\bin;"
+            + "C:\\Program Files\\WiX Toolset v3.9\\bin;"
+            + "C:\\Program Files (x86)\\WiX Toolset v3.8\\bin;"
+            + "C:\\Program Files\\WiX Toolset v3.8\\bin;"
+            + "C:\\Program Files (x86)\\WiX Toolset v3.7\\bin;"
+            + "C:\\Program Files\\WiX Toolset v3.7\\bin";
+
+    public static final BundlerParamInfo<String> TOOL_CANDLE_EXECUTABLE =
+            new WindowsBundlerParam<>(
+            I18N.getString("param.candle-path.name"),
+            I18N.getString("param.candle-path.description"),
+            "win.msi.candle.exe",
+            String.class,
+            params -> {
+                for (String dirString : (System.getenv("PATH") +
+                        AUTODETECT_DIRS).split(";")) {
+                    File f = new File(dirString.replace("\"", ""), TOOL_CANDLE);
+                    if (f.isFile()) {
+                        return f.toString();
+                    }
+                }
+                return null;
+            },
+            null);
+
+    public static final BundlerParamInfo<String> TOOL_LIGHT_EXECUTABLE =
+            new WindowsBundlerParam<>(
+            I18N.getString("param.light-path.name"),
+            I18N.getString("param.light-path.description"),
+            "win.msi.light.exe",
+            String.class,
+            params -> {
+                for (String dirString : (System.getenv("PATH") +
+                        AUTODETECT_DIRS).split(";")) {
+                    File f = new File(dirString.replace("\"", ""), TOOL_LIGHT);
+                    if (f.isFile()) {
+                        return f.toString();
+                    }
+                }
+                return null;
+            },
+            null);
+    
+    public static final StandardBundlerParam<Boolean> MENU_HINT =
+        new WindowsBundlerParam<>(
+                I18N.getString("param.menu-shortcut-hint.name"),
+                I18N.getString("param.menu-shortcut-hint.description"),
+                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)
+        );
+
+    public static final StandardBundlerParam<Boolean> SHORTCUT_HINT =
+        new WindowsBundlerParam<>(
+                I18N.getString("param.desktop-shortcut-hint.name"),
+                I18N.getString("param.desktop-shortcut-hint.description"),
+                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)
+        );
+
+    public WinMsiBundler() {
+        super();
+        baseResourceLoader = WinResources.class;
+    }
+
+
+    @Override
+    public String getName() {
+        return I18N.getString("bundler.name");
+    }
+
+    @Override
+    public String getDescription() {
+        return I18N.getString("bundler.description");
+    }
+
+    @Override
+    public String getID() {
+        return "msi";
+    }
+
+    @Override
+    public String getBundleType() {
+        return "INSTALLER";
+    }
+
+    @Override
+    public Collection<BundlerParamInfo<?>> getBundleParameters() {
+        Collection<BundlerParamInfo<?>> results = new LinkedHashSet<>();
+        results.addAll(WinAppBundler.getAppBundleParameters());
+        results.addAll(getMsiBundleParameters());
+        return results;
+    }
+
+    public static Collection<BundlerParamInfo<?>> getMsiBundleParameters() {
+        return Arrays.asList(
+                DESCRIPTION,
+                MENU_GROUP,
+                MENU_HINT,
+                PRODUCT_VERSION,
+                // RUN_AT_STARTUP,
+                SHORTCUT_HINT,
+                // SERVICE_HINT,
+                // START_ON_INSTALL,
+                // STOP_ON_UNINSTALL,
+                MSI_SYSTEM_WIDE,
+                //UPGRADE_UUID,
+                VENDOR,
+                LICENSE_FILE,
+                INSTALLDIR_CHOOSER
+        );
+    }
+
+    @Override
+    public File execute(
+            Map<String, ? super Object> params, File outputParentDir) {
+        return bundle(params, outputParentDir);
+    }
+
+    @Override
+    public boolean supported() {
+        return (Platform.getPlatform() == Platform.WINDOWS);
+    }
+
+    static class VersionExtractor extends PrintStream {
+        double version = 0f;
+
+        public VersionExtractor() {
+            super(new ByteArrayOutputStream());
+        }
+
+        double getVersion() {
+            if (version == 0f) {
+                String content =
+                        new String(((ByteArrayOutputStream) out).toByteArray());
+                Pattern pattern = Pattern.compile("version (\\d+.\\d+)");
+                Matcher matcher = pattern.matcher(content);
+                if (matcher.find()) {
+                    String v = matcher.group(1);
+                    version = new Double(v);
+                }
+            }
+            return version;
+        }
+    }
+
+    private static double findToolVersion(String toolName) {
+        try {
+            if (toolName == null || "".equals(toolName)) return 0f;
+
+            ProcessBuilder pb = new ProcessBuilder(
+                    toolName,
+                    "/?");
+            VersionExtractor ve = new VersionExtractor();
+            // not interested in the output
+            IOUtils.exec(pb, Log.isDebug(), true, ve);
+            double version = ve.getVersion();
+            Log.verbose(MessageFormat.format(
+                    I18N.getString("message.tool-version"),
+                    toolName, version));
+            return version;
+        } catch (Exception e) {
+            if (Log.isDebug()) {
+                Log.verbose(e);
+            }
+            return 0f;
+        }
+    }
+
+    @Override
+    public boolean validate(Map<String, ? super Object> p)
+            throws UnsupportedPlatformException, ConfigException {
+        try {
+            if (p == null) throw new ConfigException(
+                    I18N.getString("error.parameters-null"),
+                    I18N.getString("error.parameters-null.advice"));
+
+            // run basic validation to ensure requirements are met
+            // we are not interested in return code, only possible exception
+            APP_BUNDLER.fetchFrom(p).doValidate(p);
+
+            double candleVersion =
+                    findToolVersion(TOOL_CANDLE_EXECUTABLE.fetchFrom(p));
+            double lightVersion =
+                    findToolVersion(TOOL_LIGHT_EXECUTABLE.fetchFrom(p));
+
+            // WiX 3.0+ is required
+            double minVersion = 3.0f;
+            boolean bad = false;
+
+            if (candleVersion < minVersion) {
+                Log.verbose(MessageFormat.format(
+                        I18N.getString("message.wrong-tool-version"),
+                        TOOL_CANDLE, candleVersion, minVersion));
+                bad = true;
+            }
+            if (lightVersion < minVersion) {
+                Log.verbose(MessageFormat.format(
+                        I18N.getString("message.wrong-tool-version"),
+                        TOOL_LIGHT, lightVersion, minVersion));
+                bad = true;
+            }
+
+            if (bad){
+                throw new ConfigException(
+                        I18N.getString("error.no-wix-tools"),
+                        I18N.getString("error.no-wix-tools.advice"));
+            }
+
+            if (lightVersion >= 3.6f) {
+                Log.verbose(I18N.getString("message.use-wix36-features"));
+                p.put(CAN_USE_WIX36.getID(), Boolean.TRUE);
+            }
+
+            /********* validate bundle parameters *************/
+
+            String version = PRODUCT_VERSION.fetchFrom(p);
+            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(p);
+            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"));
+                    }
+                }
+            }
+
+            // validate license file, if used, exists in the proper place
+            if (p.containsKey(LICENSE_FILE.getID())) {
+                List<RelativeFileSet> appResourcesList =
+                        APP_RESOURCES_LIST.fetchFrom(p);
+                for (String license : LICENSE_FILE.fetchFrom(p)) {
+                    boolean found = false;
+                    for (RelativeFileSet appResources : appResourcesList) {
+                        found = found || appResources.contains(license);
+                    }
+                    if (!found) {
+                        throw new ConfigException(
+                            MessageFormat.format(I18N.getString(
+                               "error.license-missing"), license),
+                            MessageFormat.format(I18N.getString(
+                               "error.license-missing.advice"), license));
+                    }
+                }
+            }
+
+            return true;
+        } catch (RuntimeException re) {
+            if (re.getCause() instanceof ConfigException) {
+                throw (ConfigException) re.getCause();
+            } else {
+                throw new ConfigException(re);
+            }
+        }
+    }
+
+    // http://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 boolean prepareProto(Map<String, ? super Object> p)
+                throws IOException {
+        File appDir = StandardBundlerParam.getPredefinedAppImage(p);
+
+        if (appDir == null) {
+            appDir = APP_BUNDLER.fetchFrom(p).doBundle(p,
+                    MSI_IMAGE_DIR.fetchFrom(p), true);
+        }
+
+        p.put(WIN_APP_IMAGE.getID(), appDir);
+
+        List<String> licenseFiles = LICENSE_FILE.fetchFrom(p);
+        if (licenseFiles != null) {
+            // need to copy license file to the root of win.app.image
+            outerLoop:
+            for (RelativeFileSet rfs : APP_RESOURCES_LIST.fetchFrom(p)) {
+                for (String s : licenseFiles) {
+                    if (rfs.contains(s)) {
+                        File lfile = new File(rfs.getBaseDirectory(), s);
+                        File destFile = new File(appDir, lfile.getName());
+                        IOUtils.copyFile(lfile, destFile);
+                        ensureByMutationFileIsRTF(destFile);
+                        break outerLoop;
+                    }
+                }
+            }
+        }
+
+        // copy file association icons
+        List<Map<String, ? super Object>> fileAssociations =
+                FILE_ASSOCIATIONS.fetchFrom(p);
+        for (Map<String, ? super Object> fa : fileAssociations) {
+            File icon = FA_ICON.fetchFrom(fa); // TODO FA_ICON_ICO
+            if (icon == null) {
+                continue;
+            }
+
+            File faIconFile = new File(appDir, icon.getName());
+
+            if (icon.exists()) {
+                try {
+                    IOUtils.copyFile(icon, faIconFile);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        return appDir != null;
+    }
+
+    public File bundle(Map<String, ? super Object> p, File outdir) {
+        if (!outdir.isDirectory() && !outdir.mkdirs()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-create-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+        if (!outdir.canWrite()) {
+            throw new RuntimeException(MessageFormat.format(
+                    I18N.getString("error.cannot-write-to-output-dir"),
+                    outdir.getAbsolutePath()));
+        }
+
+        // validate we have valid tools before continuing
+        String light = TOOL_LIGHT_EXECUTABLE.fetchFrom(p);
+        String candle = TOOL_CANDLE_EXECUTABLE.fetchFrom(p);
+        if (light == null || !new File(light).isFile() ||
+            candle == null || !new File(candle).isFile()) {
+            Log.info(I18N.getString("error.no-wix-tools"));
+            Log.info(MessageFormat.format(
+                   I18N.getString("message.light-file-string"), light));
+            Log.info(MessageFormat.format(
+                   I18N.getString("message.candle-file-string"), candle));
+            return null;
+        }
+
+        File imageDir = MSI_IMAGE_DIR.fetchFrom(p);
+        try {
+            imageDir.mkdirs();
+
+            boolean menuShortcut = MENU_HINT.fetchFrom(p);
+            boolean desktopShortcut = SHORTCUT_HINT.fetchFrom(p);
+            if (!menuShortcut && !desktopShortcut) {
+                // both can not be false - user will not find the app
+                Log.verbose(I18N.getString("message.one-shortcut-required"));
+                p.put(MENU_HINT.getID(), true);
+            }
+
+            if (prepareProto(p) && prepareWiXConfig(p)
+                    && prepareBasicProjectConfig(p)) {
+                File configScriptSrc = getConfig_Script(p);
+                if (configScriptSrc.exists()) {
+                    // we need to be running post script in the image folder
+
+                    // NOTE: Would it be better to generate it to the image
+                    // folder and save only if "verbose" is requested?
+
+                    // for now we replicate it
+                    File configScript =
+                        new File(imageDir, configScriptSrc.getName());
+                    IOUtils.copyFile(configScriptSrc, configScript);
+                    Log.info(MessageFormat.format(
+                            I18N.getString("message.running-wsh-script"),
+                            configScript.getAbsolutePath()));
+                    IOUtils.run("wscript",
+                             configScript, ECHO_MODE.fetchFrom(p));
+                }
+                return buildMSI(p, outdir);
+            }
+            return null;
+        } catch (IOException ex) {
+            Log.verbose(ex);
+            return null;
+        } finally {
+            try {
+                if (imageDir != null &&
+                        PREDEFINED_APP_IMAGE.fetchFrom(p) == null &&
+                        (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ||
+                        !Arguments.CREATE_JRE_INSTALLER.fetchFrom(p)) && 
+                        !Log.isDebug()) {
+                    IOUtils.deleteRecursive(imageDir);
+                } else if (imageDir != null) {
+                    Log.info(MessageFormat.format(
+                            I18N.getString("message.debug-working-directory"),
+                            imageDir.getAbsolutePath()));
+                }
+                if (ECHO_MODE.fetchFrom(p)) {
+                    Log.info(MessageFormat.format(
+                            I18N.getString("message.config-save-location"),
+                            CONFIG_ROOT.fetchFrom(p).getAbsolutePath()));
+                } else {
+                    cleanupConfigFiles(p);
+                }
+            } catch (IOException ex) {
+                // noinspection ReturnInsideFinallyBlock
+                Log.debug(ex.getMessage());
+                return null;
+            }
+        }
+    }
+
+    protected void cleanupConfigFiles(Map<String, ? super Object> params) {
+        if(!StandardBundlerParam.ECHO_MODE.fetchFrom(params)) {
+            if (getConfig_ProjectFile(params) != null) {
+                getConfig_ProjectFile(params).delete();
+            }
+            if (getConfig_Script(params) != null) {
+                getConfig_Script(params).delete();
+            }
+        }
+    }
+
+    // name of post-image script
+    private File getConfig_Script(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_FS_NAME.fetchFrom(params) + "-post-image.wsf");
+    }
+
+    private boolean prepareBasicProjectConfig(
+        Map<String, ? super Object> params) throws IOException {
+        fetchResource(WinAppBundler.WIN_BUNDLER_PREFIX +
+                getConfig_Script(params).getName(),
+                I18N.getString("resource.post-install-script"),
+                (String) null,
+                getConfig_Script(params),
+                VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params));
+        return true;
+    }
+
+    private String relativePath(File basedir, File file) {
+        return file.getAbsolutePath().substring(
+                basedir.getAbsolutePath().length() + 1);
+    }
+
+    boolean prepareMainProjectFile(
+            Map<String, ? super Object> params) throws IOException {
+        Map<String, String> data = new HashMap<>();
+
+        UUID productGUID = UUID.randomUUID();
+
+        Log.verbose(MessageFormat.format(
+                I18N.getString("message.generated-product-guid"),
+                productGUID.toString()));
+
+        // we use random GUID for product itself but
+        // user provided for upgrade guid
+        // Upgrade guid is important to decide whether it is an upgrade of
+        // installed app.  I.e. we need it to be the same for
+        // 2 different versions of app if possible
+        data.put("PRODUCT_GUID", productGUID.toString());
+        data.put("PRODUCT_UPGRADE_GUID",
+                UPGRADE_UUID.fetchFrom(params).toString());
+
+        data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params));
+        data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params));
+        data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params));
+        data.put("APPLICATION_VERSION", PRODUCT_VERSION.fetchFrom(params));
+
+        // WinAppBundler will add application folder again => step out
+        File imageRootDir = WIN_APP_IMAGE.fetchFrom(params);
+        File launcher = new File(imageRootDir,
+                WinAppBundler.getLauncherName(params));
+
+        String launcherPath = relativePath(imageRootDir, launcher);
+        data.put("APPLICATION_LAUNCHER", launcherPath);
+
+        String iconPath = launcherPath.replace(".exe", ".ico");
+
+        data.put("APPLICATION_ICON", iconPath);
+
+        data.put("REGISTRY_ROOT", getRegistryRoot(params));
+
+        boolean canUseWix36Features = CAN_USE_WIX36.fetchFrom(params);
+        data.put("WIX36_ONLY_START",
+                canUseWix36Features ? "" : "<!--");
+        data.put("WIX36_ONLY_END",
+                canUseWix36Features ? "" : "-->");
+
+        if (MSI_SYSTEM_WIDE.fetchFrom(params)) {
+            data.put("INSTALL_SCOPE", "perMachine");
+        } else {
+            data.put("INSTALL_SCOPE", "perUser");
+        }
+
+        if (BIT_ARCH_64.fetchFrom(params)) {
+            data.put("PLATFORM", "x64");
+            data.put("WIN64", "yes");
+        } else {
+            data.put("PLATFORM", "x86");
+            data.put("WIN64", "no");
+        }
+
+        data.put("UI_BLOCK", getUIBlock(params));
+
+        List<Map<String, ? super Object>> secondaryLaunchers =
+                SECONDARY_LAUNCHERS.fetchFrom(params);
+
+        StringBuilder secondaryLauncherIcons = new StringBuilder();
+        for (int i = 0; i < secondaryLaunchers.size(); i++) {
+            Map<String, ? super Object> sl = secondaryLaunchers.get(i);
+            // <Icon Id="DesktopIcon.exe" SourceFile="APPLICATION_ICON" />
+            if (SHORTCUT_HINT.fetchFrom(sl) || MENU_HINT.fetchFrom(sl)) {
+                File secondaryLauncher = new File(imageRootDir,
+                        WinAppBundler.getLauncherName(sl));
+                String secondaryLauncherPath =
+                        relativePath(imageRootDir, secondaryLauncher);
+                String secondaryLauncherIconPath =
+                        secondaryLauncherPath.replace(".exe", ".ico");
+
+                secondaryLauncherIcons.append("        <Icon Id=\"Launcher");
+                secondaryLauncherIcons.append(i);
+                secondaryLauncherIcons.append(".exe\" SourceFile=\"");
+                secondaryLauncherIcons.append(secondaryLauncherIconPath);
+                secondaryLauncherIcons.append("\" />\r\n");
+            }
+        }
+        data.put("SECONDARY_LAUNCHER_ICONS", secondaryLauncherIcons.toString());
+
+        String wxs = Arguments.CREATE_JRE_INSTALLER.fetchFrom(params) ?
+                MSI_PROJECT_TEMPLATE_SERVER_JRE : MSI_PROJECT_TEMPLATE;
+        Writer w = new BufferedWriter(
+                new FileWriter(getConfig_ProjectFile(params)));
+        w.write(preprocessTextResource(
+                WinAppBundler.WIN_BUNDLER_PREFIX
+                + getConfig_ProjectFile(params).getName(),
+                I18N.getString("resource.wix-config-file"),
+                wxs, data, VERBOSE.fetchFrom(params),
+                DROP_IN_RESOURCES_ROOT.fetchFrom(params)));
+        w.close();
+        return true;
+    }
+    private int id;
+    private int compId;
+    private final static String LAUNCHER_ID = "LauncherId";
+    private final static String LAUNCHER_SVC_ID = "LauncherSvcId";
+
+    /**
+     * Overrides the dialog sequence in built-in dialog set "WixUI_InstallDir"
+     * to exclude license dialog
+     */
+    private static final String TWEAK_FOR_EXCLUDING_LICENSE =
+              "     <Publish Dialog=\"WelcomeDlg\" Control=\"Next\""
+            + "              Event=\"NewDialog\" Value=\"InstallDirDlg\""
+            + " Order=\"2\"> 1"
+            + "     </Publish>\n"
+            + "     <Publish Dialog=\"InstallDirDlg\" Control=\"Back\""
+            + "              Event=\"NewDialog\" Value=\"WelcomeDlg\""
+            + " Order=\"2\"> 1"
+            + "     </Publish>\n";
+
+    /**
+     * Creates UI element using WiX built-in dialog sets
+     *     - WixUI_InstallDir/WixUI_Minimal.
+     * The dialog sets are the closest to what we want to implement.
+     *
+     * WixUI_Minimal for license dialog only
+     * WixUI_InstallDir for installdir dialog only or for both
+     * installdir/license dialogs
+     */
+    private String getUIBlock(Map<String, ? super Object> params) {
+        String uiBlock = "     <UI/>\n"; // UI-less element
+
+        if (INSTALLDIR_CHOOSER.fetchFrom(params)) {
+            boolean enableTweakForExcludingLicense =
+                    (getLicenseFile(params) == null);
+            uiBlock = "     <UI>\n"
+                    + "     <Property Id=\"WIXUI_INSTALLDIR\""
+                    + " Value=\"APPLICATIONFOLDER\" />\n"
+                    + "     <UIRef Id=\"WixUI_InstallDir\" />\n"
+                    + (enableTweakForExcludingLicense ?
+                            TWEAK_FOR_EXCLUDING_LICENSE : "")
+                    +"     </UI>\n";
+        } else if (getLicenseFile(params) != null) {
+            uiBlock = "     <UI>\n"
+                    + "     <UIRef Id=\"WixUI_Minimal\" />\n"
+                    + "     </UI>\n";
+        }
+
+        return uiBlock;
+    }
+
+    private void walkFileTree(Map<String, ? super Object> params,
+            File root, PrintStream out, String prefix) {
+        List<File> dirs = new ArrayList<>();
+        List<File> files = new ArrayList<>();
+
+        if (!root.isDirectory()) {
+            throw new RuntimeException(
+                    MessageFormat.format(
+                            I18N.getString("error.cannot-walk-directory"),
+                            root.getAbsolutePath()));
+        }
+
+        // sort to files and dirs
+        File[] children = root.listFiles();
+        if (children != null) {
+            for (File f : children) {
+                if (f.isDirectory()) {
+                    dirs.add(f);
+                } else {
+                    files.add(f);
+                }
+            }
+        }
+
+        // have files => need to output component
+        out.println(prefix + " <Component Id=\"comp" + (compId++)
+                + "\" DiskId=\"1\""
+                + " Guid=\"" + UUID.randomUUID().toString() + "\""
+                + (BIT_ARCH_64.fetchFrom(params) ? " Win64=\"yes\"" : "")
+                + ">");
+        out.println(prefix + "  <CreateFolder/>");
+        out.println(prefix + "  <RemoveFolder Id=\"RemoveDir"
+                + (id++) + "\" On=\"uninstall\" />");
+
+        boolean needRegistryKey = !MSI_SYSTEM_WIDE.fetchFrom(params);
+        File imageRootDir = WIN_APP_IMAGE.fetchFrom(params);
+        File launcherFile =
+                new File(imageRootDir, WinAppBundler.getLauncherName(params));
+
+        // Find out if we need to use registry. We need it if
+        //  - we doing user level install as file can not serve as KeyPath
+        //  - if we adding shortcut in this component
+
+        for (File f: files) {
+            boolean isLauncher = f.equals(launcherFile);
+            if (isLauncher) {
+                needRegistryKey = true;
+            }
+        }
+
+        if (needRegistryKey) {
+            // has to be under HKCU to make WiX happy
+            out.println(prefix + "    <RegistryKey Root=\"HKCU\" "
+                    + " Key=\"Software\\" + VENDOR.fetchFrom(params) + "\\"
+                    + APP_NAME.fetchFrom(params) + "\""
+                    + (CAN_USE_WIX36.fetchFrom(params) ?
+                    ">" : " Action=\"createAndRemoveOnUninstall\">"));
+            out.println(prefix
+                    + "     <RegistryValue Name=\"Version\" Value=\""
+                    + VERSION.fetchFrom(params)
+                    + "\" Type=\"string\" KeyPath=\"yes\"/>");
+            out.println(prefix + "   </RegistryKey>");
+        }
+
+        boolean menuShortcut = MENU_HINT.fetchFrom(params);
+        boolean desktopShortcut = SHORTCUT_HINT.fetchFrom(params);
+
+        Map<String, String> idToFileMap = new TreeMap<>();
+        boolean launcherSet = false;
+
+        for (File f : files) {
+            boolean isLauncher = f.equals(launcherFile);
+
+            launcherSet = launcherSet || isLauncher;
+
+            boolean doShortcuts =
+                isLauncher && (menuShortcut || desktopShortcut);
+
+            String thisFileId = isLauncher ? LAUNCHER_ID : ("FileId" + (id++));
+            idToFileMap.put(f.getName(), thisFileId);
+
+            out.println(prefix + "   <File Id=\"" +
+                    thisFileId + "\""
+                    + " Name=\"" + f.getName() + "\" "
+                    + " Source=\"" + relativePath(imageRootDir, f) + "\""
+                    + (BIT_ARCH_64.fetchFrom(params) ?
+                    " ProcessorArchitecture=\"x64\"" : "") + ">");
+            if (doShortcuts && desktopShortcut) {
+                out.println(prefix
+                        + "  <Shortcut Id=\"desktopShortcut\" Directory="
+                        + "\"DesktopFolder\""
+                        + " Name=\"" + APP_NAME.fetchFrom(params)
+                        + "\" WorkingDirectory=\"INSTALLDIR\""
+                        + " Advertise=\"no\" Icon=\"DesktopIcon.exe\""
+                        + " IconIndex=\"0\" />");
+            }
+            if (doShortcuts && menuShortcut) {
+                out.println(prefix
+                        + "     <Shortcut Id=\"ExeShortcut\" Directory="
+                        + "\"ProgramMenuDir\""
+                        + " Name=\"" + APP_NAME.fetchFrom(params)
+                        + "\" Advertise=\"no\" Icon=\"StartMenuIcon.exe\""
+                        + " IconIndex=\"0\" />");
+            }
+
+            List<Map<String, ? super Object>> secondaryLaunchers =
+                    SECONDARY_LAUNCHERS.fetchFrom(params);
+            for (int i = 0; i < secondaryLaunchers.size(); i++) {
+                Map<String, ? super Object> sl = secondaryLaunchers.get(i);
+                File secondaryLauncherFile = new File(imageRootDir,
+                        WinAppBundler.getLauncherName(sl));
+                if (f.equals(secondaryLauncherFile)) {
+                    if (SHORTCUT_HINT.fetchFrom(sl)) {
+                        out.println(prefix
+                                + "  <Shortcut Id=\"desktopShortcut"
+                                + i + "\" Directory=\"DesktopFolder\""
+                                + " Name=\"" + APP_NAME.fetchFrom(sl)
+                                + "\" WorkingDirectory=\"INSTALLDIR\""
+                                + " Advertise=\"no\" Icon=\"Launcher"
+                                + i + ".exe\" IconIndex=\"0\" />");
+                    }
+                    if (MENU_HINT.fetchFrom(sl)) {
+                        out.println(prefix
+                                + "     <Shortcut Id=\"ExeShortcut"
+                                + i + "\" Directory=\"ProgramMenuDir\""
+                                + " Name=\"" + APP_NAME.fetchFrom(sl)
+                                + "\" Advertise=\"no\" Icon=\"Launcher"
+                                + i + ".exe\" IconIndex=\"0\" />");
+                        // Should we allow different menu groups?  Not for now.
+                    }
+                }
+            }
+            out.println(prefix + "   </File>");
+        }
+
+        if (launcherSet) {
+            List<Map<String, ? super Object>> fileAssociations =
+                FILE_ASSOCIATIONS.fetchFrom(params);
+            String regName = APP_REGISTRY_NAME.fetchFrom(params);
+            Set<String> defaultedMimes = new TreeSet<>();
+            int count = 0;
+            for (Map<String, ? super Object> fa : fileAssociations) {
+                String description = FA_DESCRIPTION.fetchFrom(fa);
+                List<String> extensions = FA_EXTENSIONS.fetchFrom(fa);
+                List<String> mimeTypes = FA_CONTENT_TYPE.fetchFrom(fa);
+                File icon = FA_ICON.fetchFrom(fa); // TODO FA_ICON_ICO
+
+                String mime = (mimeTypes == null ||
+                    mimeTypes.isEmpty()) ? null : mimeTypes.get(0);
+
+                if (extensions == null) {
+                    Log.info(I18N.getString(
+                          "message.creating-association-with-null-extension"));
+
+                    String entryName = regName + "File";
+                    if (count > 0) {
+                        entryName += "." + count;
+                    }
+                    count++;
+                    out.print(prefix + "   <ProgId Id='" + entryName
+                            + "' Description='" + description + "'");
+                    if (icon != null && icon.exists()) {
+                        out.print(" Icon='" + idToFileMap.get(icon.getName())
+                                + "' IconIndex='0'");
+                    }
+                    out.println(" />");
+                } else {
+                    for (String ext : extensions) {
+                        String entryName = regName + "File";
+                        if (count > 0) {
+                            entryName += "." + count;
+                        }
+                        count++;
+
+                        out.print(prefix + "   <ProgId Id='" + entryName
+                                + "' Description='" + description + "'");
+                        if (icon != null && icon.exists()) {
+                            out.print(" Icon='"
+                                    + idToFileMap.get(icon.getName())
+                                    + "' IconIndex='0'");
+                        }
+                        out.println(">");
+
+                        if (extensions == null) {
+                            Log.info(I18N.getString(
+                            "message.creating-association-with-null-extension"));
+                        } else {
+                            out.print(prefix + "    <Extension Id='"
+                                    + ext + "' Advertise='no'");
+                            if (mime == null) {
+                                out.println(">");
+                            } else {
+                                out.println(" ContentType='" + mime + "'>");
+                                if (!defaultedMimes.contains(mime)) {
+                                    out.println(prefix
+                                            + "      <MIME ContentType='"
+                                            + mime + "' Default='yes' />");
+                                    defaultedMimes.add(mime);
+                                }
+                            }
+                            out.println(prefix
+                                    + "      <Verb Id='open' Command='Open' "
+                                    + "TargetFile='" + LAUNCHER_ID
+                                    + "' Argument='\"%1\"' />");
+                            out.println(prefix + "    </Extension>");
+                        }
+                        out.println(prefix + "   </ProgId>");
+                    }
+                }
+            }
+        }
+
+        out.println(prefix + " </Component>");
+
+        for (File d : dirs) {
+            out.println(prefix + " <Directory Id=\"dirid" + (id++)
+                    + "\" Name=\"" + d.getName() + "\">");
+            walkFileTree(params, d, out, prefix + " ");
+            out.println(prefix + " </Directory>");
+        }
+    }
+
+    String getRegistryRoot(Map<String, ? super Object> params) {
+        if (MSI_SYSTEM_WIDE.fetchFrom(params)) {
+            return "HKLM";
+        } else {
+            return "HKCU";
+        }
+    }
+
+    boolean prepareContentList(Map<String, ? super Object> params)
+            throws FileNotFoundException {
+        File f = new File(
+                CONFIG_ROOT.fetchFrom(params), MSI_PROJECT_CONTENT_FILE);
+        PrintStream out = new PrintStream(f);
+
+        // opening
+        out.println("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
+        out.println("<Include>");
+
+        out.println(" <Directory Id=\"TARGETDIR\" Name=\"SourceDir\">");
+        if (MSI_SYSTEM_WIDE.fetchFrom(params)) {
+            // install to programfiles
+            if (BIT_ARCH_64.fetchFrom(params)) {
+                out.println("  <Directory Id=\"ProgramFiles64Folder\" "
+                        + "Name=\"PFiles\">");
+            } else {
+                out.println("  <Directory Id=\"ProgramFilesFolder\" "
+                        + "Name=\"PFiles\">");
+            }
+        } else {
+            // install to user folder
+            out.println(
+                    "  <Directory Name=\"AppData\" Id=\"LocalAppDataFolder\">");
+        }
+        out.println("   <Directory Id=\"APPLICATIONFOLDER\" Name=\""
+                + APP_NAME.fetchFrom(params) + "\">");
+
+        // dynamic part
+        id = 0;
+        compId = 0; // reset counters
+        walkFileTree(params, WIN_APP_IMAGE.fetchFrom(params), out, "    ");
+
+        // closing
+        out.println("   </Directory>");
+        out.println("  </Directory>");
+
+        // for shortcuts
+        if (SHORTCUT_HINT.fetchFrom(params)) {
+            out.println("  <Directory Id=\"DesktopFolder\" />");
+        }
+        if (MENU_HINT.fetchFrom(params)) {
+            out.println("  <Directory Id=\"ProgramMenuFolder\">");
+            out.println("    <Directory Id=\"ProgramMenuDir\" Name=\""
+                    + MENU_GROUP.fetchFrom(params) + "\">");
+            out.println("      <Component Id=\"comp" + (compId++) + "\""
+                    + " Guid=\"" + UUID.randomUUID().toString() + "\""
+                    + (BIT_ARCH_64.fetchFrom(params) ? " Win64=\"yes\"" : "")
+                    + ">");
+            out.println("        <RemoveFolder Id=\"ProgramMenuDir\" "
+                    + "On=\"uninstall\" />");
+            // This has to be under HKCU to make WiX happy.
+            // There are numberous discussions on this amoung WiX users
+            // (if user A installs and user B uninstalls key is left behind)
+            // there are suggested workarounds but none of them are appealing.
+            // Leave it for now
+            out.println(
+                    "         <RegistryValue Root=\"HKCU\" Key=\"Software\\"
+                    + VENDOR.fetchFrom(params) + "\\"
+                    + APP_NAME.fetchFrom(params)
+                    + "\" Type=\"string\" Value=\"\" />");
+            out.println("      </Component>");
+            out.println("    </Directory>");
+            out.println(" </Directory>");
+        }
+
+        out.println(" </Directory>");
+
+        out.println(" <Feature Id=\"DefaultFeature\" "
+                + "Title=\"Main Feature\" Level=\"1\">");
+        for (int j = 0; j < compId; j++) {
+            out.println("    <ComponentRef Id=\"comp" + j + "\" />");
+        }
+        // component is defined in the template.wsx
+        out.println("    <ComponentRef Id=\"CleanupMainApplicationFolder\" />");
+        out.println(" </Feature>");
+        out.println("</Include>");
+
+        out.close();
+        return true;
+    }
+
+    private File getConfig_ProjectFile(Map<String, ? super Object> params) {
+        return new File(CONFIG_ROOT.fetchFrom(params),
+                APP_NAME.fetchFrom(params) + ".wxs");
+    }
+
+    private String getLicenseFile(Map<String, ? super Object> params) {
+        List<String> licenseFiles = LICENSE_FILE.fetchFrom(params);
+        if (licenseFiles == null || licenseFiles.isEmpty()) {
+            return null;
+        } else {
+            return licenseFiles.get(0);
+        }
+    }
+
+    private boolean prepareWiXConfig(
+            Map<String, ? super Object> params) throws IOException {
+        return prepareMainProjectFile(params) && prepareContentList(params);
+
+    }
+    private final static String MSI_PROJECT_TEMPLATE = "template.wxs";
+    private final static String MSI_PROJECT_TEMPLATE_SERVER_JRE =
+            "template.server.jre.wxs";
+    private final static String MSI_PROJECT_CONTENT_FILE = "bundle.wxi";
+
+    private File buildMSI(Map<String, ? super Object> params, File outdir)
+            throws IOException {
+        File tmpDir = new File(BUILD_ROOT.fetchFrom(params), "tmp");
+        File candleOut = new File(
+                tmpDir, APP_NAME.fetchFrom(params) +".wixobj");
+        File msiOut = new File(
+                outdir, INSTALLER_FILE_NAME.fetchFrom(params) + ".msi");
+
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.preparing-msi-config"), msiOut.getAbsolutePath()));
+
+        msiOut.getParentFile().mkdirs();
+
+        // run candle
+        ProcessBuilder pb = new ProcessBuilder(
+                TOOL_CANDLE_EXECUTABLE.fetchFrom(params),
+                "-nologo",
+                getConfig_ProjectFile(params).getAbsolutePath(),
+                "-ext", "WixUtilExtension",
+                "-out", candleOut.getAbsolutePath());
+        pb = pb.directory(WIN_APP_IMAGE.fetchFrom(params));
+        IOUtils.exec(pb, ECHO_MODE.fetchFrom(params));
+
+        Log.verbose(MessageFormat.format(I18N.getString(
+                "message.generating-msi"), msiOut.getAbsolutePath()));
+
+        boolean enableLicenseUI = (getLicenseFile(params) != null);
+        boolean enableInstalldirUI = INSTALLDIR_CHOOSER.fetchFrom(params);
+
+        List<String> commandLine = new ArrayList<>();
+
+        commandLine.add(TOOL_LIGHT_EXECUTABLE.fetchFrom(params));
+        if (enableLicenseUI) {
+            commandLine.add("-dWixUILicenseRtf="+getLicenseFile(params));
+        }
+        commandLine.add("-nologo");
+        commandLine.add("-spdb");
+        commandLine.add("-sice:60");
+                // ignore warnings due to "missing launcguage info" (ICE60)
+        commandLine.add(candleOut.getAbsolutePath());
+        commandLine.add("-ext");
+        commandLine.add("WixUtilExtension");
+        if (enableLicenseUI || enableInstalldirUI) {
+            commandLine.add("-ext");
+            commandLine.add("WixUIExtension.dll");
+        }
+        commandLine.add("-out");
+        commandLine.add(msiOut.getAbsolutePath());
+
+        //create .msi
+        pb = new ProcessBuilder(commandLine);
+
+        pb = pb.directory(WIN_APP_IMAGE.fetchFrom(params));
+        IOUtils.exec(pb, ECHO_MODE.fetchFrom(params));
+
+        candleOut.delete();
+        IOUtils.deleteRecursive(tmpDir);
+
+        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);
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/windows/WindowsBundlerParam.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2014, 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.packager.internal.windows;
+
+import jdk.packager.internal.BundlerParamInfo;
+import jdk.packager.internal.JreUtils;
+import jdk.packager.internal.StandardBundlerParam;
+import jdk.packager.internal.Arguments;
+import jdk.packager.internal.RelativeFileSet;
+import jdk.packager.internal.bundlers.BundleParams;
+
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import static jdk.packager.internal.JreUtils.extractJreAsRelativeFileSet;
+
+
+public class WindowsBundlerParam<T> extends StandardBundlerParam<T> {
+
+    private static final ResourceBundle I18N = ResourceBundle.getBundle(
+            "jdk.packager.internal.resources.windows.WindowsBundlerParam");
+
+    public WindowsBundlerParam(String name, String description, String id,
+            Class<T> valueType,
+            Function<Map<String, ? super Object>, T> defaultValueFunction,
+            BiFunction<String,
+            Map<String, ? super Object>, T> stringConverter) {
+        super(name, description, id, valueType,
+                defaultValueFunction, stringConverter);
+    }
+
+    public static final BundlerParamInfo<String> INSTALLER_FILE_NAME =
+            new StandardBundlerParam<> (
+            I18N.getString("param.installer-name.name"),
+            I18N.getString("param.installer-name.description"),
+            "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);
+
+    public static final BundlerParamInfo<String> APP_REGISTRY_NAME =
+            new StandardBundlerParam<> (
+            I18N.getString("param.registry-name.name"),
+            I18N.getString("param.registry-name.description"),
+            Arguments.CLIOptions.WIN_REGISTRY_NAME.getId(),
+            String.class,
+            params -> {
+                String nm = APP_NAME.fetchFrom(params);
+                if (nm == null) return null;
+
+                return nm.replaceAll("[^-a-zA-Z\\.0-9]", "");
+            },
+            (s, p) -> s);
+
+    public static final StandardBundlerParam<String> MENU_GROUP =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.menu-group.name"),
+                    I18N.getString("param.menu-group.description"),
+                    Arguments.CLIOptions.WIN_MENU_GROUP.getId(),
+                    String.class,
+                    params -> params.containsKey(VENDOR.getID())
+                            ? VENDOR.fetchFrom(params)
+                            : params.containsKey(CATEGORY.getID())
+                            ? CATEGORY.fetchFrom(params)
+                            : I18N.getString("param.menu-group.default"),
+                    (s, p) -> s
+            );
+
+    public static final StandardBundlerParam<Boolean> BIT_ARCH_64 =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.64-bit.name"),
+                    I18N.getString("param.64-bit.description"),
+                    "win.64Bit",
+                    Boolean.class,
+                    params -> System.getProperty("os.arch").contains("64"),
+                    (s, p) -> Boolean.valueOf(s)
+            );
+
+    public static final StandardBundlerParam<Boolean> BIT_ARCH_64_RUNTIME =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.runtime-64-bit.name"),
+                    I18N.getString("param.runtime-64-bit.description"),
+                    "win.64BitJreRuntime",
+                    Boolean.class,
+                    params -> {
+                        WinAppBundler.extractFlagsFromRuntime(params);
+                        return "64".equals(params.get(".runtime.bit-arch"));
+                    },
+                    (s, p) -> Boolean.valueOf(s)
+            );
+
+    // Subsetting of JRE is restricted.
+    // JRE README defines what is allowed to strip:
+    // http://www.oracle.com/technetwork/java/javase/jre-8-readme-2095710.html
+    public static final BundlerParamInfo<JreUtils.Rule[]> WIN_JRE_RULES =
+            new StandardBundlerParam<>(
+            "",
+            "",
+            ".win.runtime.rules",
+            JreUtils.Rule[].class,
+            params -> new JreUtils.Rule[]{
+                    JreUtils.Rule.prefixNeg("\\bin\\new_plugin"),
+                    JreUtils.Rule.prefixNeg("\\lib\\deploy"),
+                    JreUtils.Rule.suffixNeg(".pdb"),
+                    JreUtils.Rule.suffixNeg(".map"),
+                    JreUtils.Rule.suffixNeg("axbridge.dll"),
+                    JreUtils.Rule.suffixNeg("eula.dll"),
+                    JreUtils.Rule.substrNeg("javacpl"),
+                    JreUtils.Rule.suffixNeg("wsdetect.dll"),
+                    JreUtils.Rule.substrNeg("eployjava1.dll"),
+                    // NP and IE versions
+                    JreUtils.Rule.substrNeg("bin\\jp2"),
+                    JreUtils.Rule.substrNeg("bin\\jpi"),
+                    // Rule.suffixNeg("lib\\ext"),
+                    // need some of jars there for https to work
+                    JreUtils.Rule.suffixNeg("ssv.dll"),
+                    JreUtils.Rule.substrNeg("npjpi"),
+                    JreUtils.Rule.substrNeg("npoji"),
+                    JreUtils.Rule.suffixNeg(".exe"),
+                    // keep core deploy files as JavaFX APIs use them
+                    // Rule.suffixNeg("deploy.dll"),
+                    JreUtils.Rule.suffixNeg("deploy.jar"),
+                    // Rule.suffixNeg("javaws.jar"),
+                    // Rule.suffixNeg("plugin.jar"),
+                    JreUtils.Rule.suffix(".jar")
+            },
+            (s, p) -> null
+    );
+
+    public static final BundlerParamInfo<RelativeFileSet> WIN_RUNTIME =
+            new StandardBundlerParam<>(
+            I18N.getString("param.runtime.name"),
+            I18N.getString("param.runtime.description"),
+            BundleParams.PARAM_RUNTIME,
+            RelativeFileSet.class,
+            params -> extractJreAsRelativeFileSet(
+                    System.getProperty("java.home"),
+                    WIN_JRE_RULES.fetchFrom(params)),
+            (s, p) -> extractJreAsRelativeFileSet(s,
+                    WIN_JRE_RULES.fetchFrom(p))
+    );
+
+    public static final BundlerParamInfo<Boolean> INSTALLDIR_CHOOSER =
+            new StandardBundlerParam<> (
+            I18N.getString("param.installdir-chooser.name"),
+            I18N.getString("param.installdir-chooser.description"),
+            Arguments.CLIOptions.WIN_DIR_CHOOSER.getId(),
+            Boolean.class,
+            params -> Boolean.FALSE,
+            (s, p) -> Boolean.valueOf(s)
+    );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/jdk/packager/internal/windows/WindowsDefender.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.windows;
+
+import jdk.packager.internal.Platform;
+import java.util.List;
+
+public final class WindowsDefender {
+
+    private WindowsDefender() {}
+
+    public static final boolean isThereAPotentialWindowsDefenderIssue() {
+        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() &&
+                !isTempDirectoryInExclusionPath()) {
+                result = true;
+            }
+        }
+
+        return result;
+    }
+
+    private static boolean isTempDirectoryInExclusionPath() {
+        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();
+        String tempDirectory = getUserTempDirectory();
+
+        for (String s : paths) {
+            if (s.equals(tempDirectory)) {
+                result = true;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    public 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.packager/windows/classes/jdk/packager/internal/windows/WindowsRegistry.java	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2012, 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.packager.internal.windows;
+
+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;
+
+import static jdk.packager.internal.IOUtils.exec;
+
+public final class WindowsRegistry {
+
+    private WindowsRegistry() {}
+
+    /**
+     * Reads the registry value for DisableRealtimeMonitoring.
+     * @return true if DisableRealtimeMonitoring is set to 0x1,
+     *         false otherwise.
+     */
+    public static final boolean readDisableRealtimeMonitoring() {
+        boolean result = false;
+        final String key =
+            "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows Defender\\Real-Time Protection";
+        final String subkey = "DisableRealtimeMonitoring";
+        String value = readRegistry(key, subkey);
+
+        if (!value.isEmpty()) {
+            // This code could be written better but this works. It validates
+            // that the result of readRegistry returned what we expect and then
+            // checks for a 0x0 or 0x1. 0x0 means real time monitoring is
+            // on, 0x1 means it is off. So this function returns true if
+            // real-time-monitoring is disabled.
+            int index = value.indexOf(subkey);
+            value = value.substring(index + subkey.length());
+            String reg = "REG_DWORD";
+            index = value.indexOf(reg);
+            value = value.substring(index + reg.length());
+            String hex = "0x";
+            index = value.indexOf(hex);
+            value = value.substring(index + hex.length());
+
+            if (value.equals("1")) {
+                result = true;
+            }
+        }
+
+        return result;
+    }
+
+    public static final List<String> readExclusionsPaths() {
+        List<String> result = new ArrayList();
+        final String key =
+                "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows Defender\\Exclusions\\Paths";
+        String value = readRegistry(key, "");
+
+        if (!value.isEmpty()) {
+            final String reg = "REG_DWORD";
+            final String hex = "0x0";
+
+            int index = value.indexOf(key);
+            if (index == 0) {
+                value = value.substring(index + key.length());
+
+                while (value.length() > 0) {
+                    index = value.indexOf(reg);
+                    String name = value.substring(0, index);
+                    value = value.substring(index + reg.length());
+                    index = value.indexOf(hex);
+                    value = value.substring(index + hex.length());
+
+                    if (index > 0) {
+                        name = name.trim();
+                        result.add(name);
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * @param key in the registry
+     * @param subkey in the registry key
+     * @return registry value or null if not found
+     */
+    public static final String readRegistry(String key, String subkey){
+        String result = "";
+
+        try {
+            List<String> buildOptions = new ArrayList<>();
+            buildOptions.add("reg");
+            buildOptions.add("query");
+            buildOptions.add("\"" + key + "\"");
+
+            if (!subkey.isEmpty()) {
+                buildOptions.add("/v");
+                buildOptions.add(subkey);
+            }
+
+            try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    PrintStream ps = new PrintStream(baos)) {
+                ProcessBuilder security = new ProcessBuilder(buildOptions);
+                exec(security, false, false, ps);
+                BufferedReader bfReader = new BufferedReader(
+                        new InputStreamReader(
+                        new ByteArrayInputStream(baos.toByteArray())));
+                String line = null;
+
+                while((line = bfReader.readLine()) != null){
+                    result += line;
+                }
+            }
+            catch (IOException e) {
+            }
+        }
+        catch (Exception e) {
+        }
+
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/classes/module-info.java.extra	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 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.
+ */
+
+
+provides jdk.packager.internal.Bundler with
+    jdk.packager.internal.windows.WinAppBundler,
+    jdk.packager.internal.windows.WinMsiBundler;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/native/jpackager/ByteBuffer.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,77 @@
+/*
+* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.  Oracle designates this
+* particular file as subject to the "Classpath" exception as provided
+* by Oracle in the LICENSE file that accompanied this code.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please 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.packager/windows/native/jpackager/ByteBuffer.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,56 @@
+/*
+* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.  Oracle designates this
+* particular file as subject to the "Classpath" exception as provided
+* by Oracle in the LICENSE file that accompanied this code.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please 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>
+
+using std::wstring;
+
+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:
+    std::vector<BYTE> buffer;
+};
+
+#endif // BYTEBUFFER_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/native/jpackager/IconSwap.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// iconswap.cpp : Defines the entry point for the console application.
+//
+
+//Define Windows compatibility requirements
+//XP or later
+#define WINVER 0x0501
+#define _WIN32_WINNT 0x0501
+
+#include <tchar.h>
+#include <stdio.h>
+#include <windows.h>
+#include <stdlib.h>
+#include <iostream>
+#include <malloc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <strsafe.h>
+#include <Shellapi.h>
+
+
+// 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;
+    DWORD error = GetLastError();
+
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+        FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
+        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+        (LPTSTR) &message, 0, NULL);
+
+    wprintf(L"%s\n", (__wchar_t *) message); // VS2017 - FIXME
+    LocalFree(message);
+}
+
+bool ChangeIcon(_TCHAR* iconFileName, _TCHAR* executableFileName)
+{
+    bool result = false;
+
+    DWORD dwData = 1;
+    WORD language = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
+
+    _TCHAR* iconExtension = wcsrchr(iconFileName, '.');
+    if (iconExtension == NULL || wcscmp(iconExtension, L".ico") != 0) {
+        wprintf(L"Unknown icon format - please provide .ICO file.\n");
+        return result;
+    }
+
+    HANDLE icon = CreateFile(iconFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (icon == INVALID_HANDLE_VALUE) {
+        PrintError();
+        return result;
+    }
+
+    // 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);
+        wprintf(L"Unknown error.\n");
+    }
+
+    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);
+        wprintf(L"Unknown error.\n");
+    }
+
+    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( executableFileName, FALSE );
+
+    if (update == NULL) {
+        free(lpid);
+        free(lpgid);
+        CloseHandle(icon);
+        PrintError();
+        return result;
+    }
+
+    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 result;
+        }
+        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 result;
+    }
+
+    free(lpgid);
+
+    if (EndUpdateResource(update, FALSE) == FALSE) {
+        PrintError();
+        return result;
+    }
+
+    result = true;
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/native/jpackager/IconSwap.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,33 @@
+/*
+* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.  Oracle designates this
+* particular file as subject to the "Classpath" exception as provided
+* by Oracle in the LICENSE file that accompanied this code.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please 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 <tchar.h>
+
+bool ChangeIcon(_TCHAR* iconFileName, _TCHAR* executableFileName);
+
+#endif // ICONSWAP_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/native/jpackager/VersionInfoSwap.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,288 @@
+/*
+* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.  Oracle designates this
+* particular file as subject to the "Classpath" exception as provided
+* by Oracle in the LICENSE file that accompanied this code.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please 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>
+
+
+/*
+ * Usage: VersionInfoSwap.exe [Property file] [Executable file]
+ *
+ * [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.
+ *
+ */
+
+bool VersionInfoSwap::PatchExecutable() {
+    bool b = LoadFromPropertyFile();
+    if (!b) {
+        return false;
+    }
+
+    ByteBuffer buf;
+    CreateNewResource(&buf);
+    b = this->UpdateResource(buf.getPtr(), static_cast<DWORD>(buf.getPos()));
+    if (!b) {
+        return false;
+    }
+    return true;
+}
+
+bool VersionInfoSwap::LoadFromPropertyFile() {
+
+    bool result = false;
+    std::wifstream stream(m_propFileName.data());
+
+    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);
+
+    if (stream.is_open() == true) {
+        int lineNumber = 1;
+        while (stream.eof() == false) {
+            wstring line;
+            std::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;
+                } else {
+                    fwprintf(stderr, TEXT("Unable to find delimiter at line %d\n"), lineNumber);
+                }
+            }
+            lineNumber++;
+        }
+        result = true;
+    } else {
+        fwprintf(stderr, TEXT("Unable to read property file\n"));
+    }
+
+    return result;
+}
+
+
+/*
+ * Creates new version resource
+ *
+ * MSND docs for VS_VERSION_INFO structure
+ *     https://msdn.microsoft.com/en-us/library/ms647001(v=vs.85).aspx
+ */
+void 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;
+    FillFixedFileInfo(&fxi);
+    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
+    std::vector<wstring> keys;
+    for (std::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);
+    // "040904B0" = LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP
+    buf->AppendWORD(0x0409);
+    buf->AppendWORD(0x04B0);
+
+    buf->ReplaceWORD(varFileInfoStart, static_cast<WORD>(buf->getPos() - varFileInfoStart));
+    buf->ReplaceWORD(versionInfoStart, static_cast<WORD>(buf->getPos() - versionInfoStart));
+}
+
+void 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) {
+        fwprintf(stderr, TEXT("Unable to parse FileVersion value\n"));
+    }
+
+    ret = _stscanf_s(productVersion.c_str(), TEXT("%d.%d.%d.%d"), &pv_1, &pv_2, &pv_3, &pv_4);
+    if (ret <= 0 || ret > 4) {
+        fwprintf(stderr, TEXT("Unable to parse ProductVersion value\n"));
+    }
+
+    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;
+    if (m_props.count(TEXT("PrivateBuild"))) {
+        fxi->dwFileFlags |= VS_FF_PRIVATEBUILD;
+    }
+    if (m_props.count(TEXT("SpecialBuild"))) {
+        fxi->dwFileFlags |= VS_FF_SPECIALBUILD;
+    }
+    fxi->dwFileOS = VOS_NT_WINDOWS32;
+
+    wstring exeExt = m_exeFileName.substr(m_exeFileName.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;
+}
+
+/*
+ * Adds new resource in the executable
+ */
+bool VersionInfoSwap::UpdateResource(LPVOID lpResLock, DWORD size) {
+
+    HANDLE hUpdateRes;
+    BOOL r;
+
+    hUpdateRes = ::BeginUpdateResource(m_exeFileName.c_str(), FALSE);
+    if (hUpdateRes == NULL) {
+        fwprintf(stderr, TEXT("Could not open file for writing\n"));
+        return false;
+    }
+
+    r = ::UpdateResource(hUpdateRes,
+        RT_VERSION,
+        MAKEINTRESOURCE(VS_VERSION_INFO),
+        MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+        lpResLock,
+        size);
+
+    if (!r) {
+        fwprintf(stderr, TEXT("Could not add resource\n"));
+        return false;
+    }
+
+    if (!::EndUpdateResource(hUpdateRes, FALSE)) {
+        fwprintf(stderr, TEXT("Could not write changes to file\n"));
+        return false;
+    }
+
+    return true;
+}
+
+VersionInfoSwap::VersionInfoSwap(TCHAR *propFileName, TCHAR *exeFileName)
+{
+    m_propFileName = propFileName;
+    m_exeFileName = exeFileName;
+}
+
+VersionInfoSwap::~VersionInfoSwap()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/native/jpackager/VersionInfoSwap.h	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.  Oracle designates this
+* particular file as subject to the "Classpath" exception as provided
+* by Oracle in the LICENSE file that accompanied this code.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please 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>
+
+class VersionInfoSwap {
+public:
+    VersionInfoSwap(TCHAR *propFileName, TCHAR *exeFileName);
+    ~VersionInfoSwap();
+
+    bool PatchExecutable();
+
+private:
+    wstring m_propFileName;
+    wstring m_exeFileName;
+
+    std::map<wstring, wstring> m_props;
+
+    bool LoadFromPropertyFile();
+    void CreateNewResource(ByteBuffer *buf);
+    bool UpdateResource(LPVOID lpResLock, DWORD size);
+    void FillFixedFileInfo(VS_FIXEDFILEINFO *fxi);
+};
+
+#endif // VERSIONINFOSWAP_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/native/jpackager/javapackager.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,577 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <windows.h>
+
+#include "IconSwap.h"
+#include "VersionInfoSwap.h"
+
+#define _DEBUG true
+
+#ifdef _DEBUG
+#include <iostream>
+#include <sstream>
+#endif
+
+using namespace std;
+
+#define MAX_KEY_LENGTH 255
+#define MAX_VALUE_NAME 16383
+#define TRAILING_PATHSEPARATOR '\\'
+
+bool from_string(int &result, string &str) {
+    const char *p = str.c_str();
+    int res = 0;
+    for (int index = 0;; index++) {
+        char c = str[index];
+        if (c == 0 && index > 0) {
+            result = res;
+            return true;
+        }
+        if (c < '0' || c > '9')
+            return false;
+        res = res * 10 + (c - '0');
+    }
+}
+
+void PrintCSBackupAPIErrorMessage(DWORD dwErr) {
+
+    char wszMsgBuff[512]; // Buffer for text.
+
+    DWORD dwChars; // Number of chars returned.
+
+    // Try to get the message from the system errors.
+    dwChars = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+            FORMAT_MESSAGE_IGNORE_INSERTS,
+            NULL,
+            dwErr,
+            0,
+            wszMsgBuff,
+            512,
+            NULL);
+
+    if (0 == dwChars) {
+        // The error code did not exist in the system errors.
+        // Try ntdsbmsg.dll for the error code.
+        HINSTANCE hInst;
+
+        // Load the library.
+        hInst = LoadLibraryA("ntdsbmsg.dll");
+        if (NULL == hInst) {
+#ifdef _DEBUG
+            cerr << "cannot load ntdsbmsg.dll\n";
+#endif
+            return;
+        }
+
+        // Try getting message text from ntdsbmsg.
+        dwChars = FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE |
+                FORMAT_MESSAGE_IGNORE_INSERTS,
+                hInst,
+                dwErr,
+                0,
+                wszMsgBuff,
+                512,
+                NULL);
+
+        // Free the library.
+        FreeLibrary(hInst);
+    }
+
+    // Display the error message, or generic text if not found.
+#ifdef _DEBUG
+    cerr << "Error value: " << dwErr << " Message: " << ((dwChars > 0) ? wszMsgBuff : "Error message not found.") << endl;
+#endif
+}
+
+class JavaVersion {
+public:
+    int v1;
+    int v2;
+    int v3;
+    std::wstring home;
+    std::wstring path;
+
+    JavaVersion(int pv1, int pv2, int pv3) {
+        v1 = pv1;
+        v2 = pv2;
+        v3 = pv3;
+    }
+
+    bool operator>(const JavaVersion &other) const {
+        if (v1 > other.v1)
+            return true;
+        if (v1 == other.v1) {
+            if (v2 > other.v2)
+                return true;
+            if (v2 == other.v2)
+                return v3 > other.v3;
+        }
+        return false;
+    }
+
+    bool operator>=(const JavaVersion &other) const {
+        if (v1 > other.v1)
+            return true;
+        if (v1 == other.v1) {
+            if (v2 > other.v2)
+                return true;
+            if (v2 == other.v2)
+                return v3 >= other.v3;
+        }
+        return false;
+    }
+
+    bool operator<(const JavaVersion &other) const {
+        if (v1 < other.v1)
+            return true;
+        if (v1 == other.v1) {
+            if (v2 < other.v2)
+                return true;
+            if (v2 == other.v2)
+                return v3 < other.v3;
+        }
+        return false;
+    }
+};
+
+class EnvironmentVariable {
+private:
+    std::wstring FValue;
+
+public:
+    EnvironmentVariable(std::wstring Name) {
+        wchar_t* value;
+        size_t requiredSize;
+
+        _wgetenv_s(&requiredSize, NULL, 0, Name.data());
+
+        if (requiredSize != 0) {
+            value = (wchar_t*)malloc(requiredSize * sizeof(wchar_t));
+            if (value)
+            {
+                // Get the value of the LIB environment variable.
+                _wgetenv_s(&requiredSize, value, requiredSize, Name.data());
+                FValue = value;
+            }
+        }
+    }
+
+    std::wstring get() {
+        return FValue;
+    }
+
+    bool exists() {
+        return !FValue.empty();
+    }
+};
+
+bool checkJavaHome(HKEY key, const char * sKey, const char * jv, JavaVersion *version) {
+    char p[MAX_KEY_LENGTH];
+    HKEY hKey;
+    bool result = false;
+    int res;
+
+    strcpy_s(p, MAX_KEY_LENGTH, sKey);
+    strcat_s(p, MAX_KEY_LENGTH - strlen(p), "\\");
+    strcat_s(p, MAX_KEY_LENGTH - strlen(p), jv);
+
+    if (RegOpenKeyExA(key,
+            p,
+            0,
+            KEY_READ,
+            &hKey) == ERROR_SUCCESS
+            ) {
+        DWORD ot = REG_SZ;
+        DWORD size = 255;
+        wchar_t data[MAX_PATH] = { 0 };
+        if ((res = RegQueryValueEx(hKey, L"JavaHome", NULL, &ot, (BYTE *)data, &size)) == ERROR_SUCCESS) {
+            version->home = data;
+            std::wstring ldata = std::wstring(data) + L"\\bin\\java.exe";
+            version->path = data;
+            result = GetFileAttributes(data) != 0xFFFFFFFF;
+        }
+        else {
+            PrintCSBackupAPIErrorMessage(res);
+            result = false;
+        }
+        RegCloseKey(hKey);
+    }
+    else {
+#ifdef _DEBUG
+        cerr << "Can not open registry key" << endl;
+#endif
+        result = false;
+    }
+
+    return result;
+}
+
+JavaVersion * parseName(const char * jName) {
+    string s(jName);
+
+    if (s.length() == 0) {
+        return NULL;
+    }
+
+    string n;
+    string::size_type pos;
+
+    pos = s.find_first_of(".");
+    if (pos != string::npos) {
+        n = s.substr(0, pos);
+        s = s.substr(pos + 1);
+    }
+    else {
+        n = s;
+        s = "";
+    }
+
+    int v1 = 0;
+
+    if (n.length() > 0) {
+        if (!from_string(v1, n))
+            return NULL;
+    }
+
+
+    pos = s.find_first_of(".");
+    if (pos != string::npos) {
+        n = s.substr(0, pos);
+        s = s.substr(pos + 1);
+    }
+    else {
+        n = s;
+        s = "";
+    }
+
+    int v2 = 0;
+
+    if (n.length() > 0) {
+        if (!from_string(v2, n))
+            return NULL;
+    }
+
+
+    size_t nn = s.length();
+    for (size_t i = 0; i < s.length(); i++) {
+        string c = s.substr(i, 1);
+        int tmp;
+        if (!from_string(tmp, c)) {
+            nn = i;
+            break;
+        }
+    }
+
+    n = s.substr(0, nn);
+    if (nn < s.length()) {
+        s = s.substr(nn + 1);
+    }
+    else s = "";
+
+    int v3 = 0;
+
+    if (n.length() > 0) {
+        if (!from_string(v3, n))
+            v3 = 0;
+    }
+
+    int v4 = 0;
+
+    // update version
+    if (s.length() > 0) {
+        nn = s.length();
+        for (size_t i = 0; i < s.length(); i++) {
+            string c = s.substr(i, 1);
+            int tmp;
+            if (!from_string(tmp, c)) {
+                nn = i;
+                break;
+            }
+        }
+
+        n = s.substr(0, nn);
+
+        if (n.length() > 0) {
+            if (!from_string(v4, n))
+                v4 = 0;
+        }
+    }
+
+    return new JavaVersion(v2, v3, v4);
+}
+
+JavaVersion * GetMaxVersion(HKEY key, const char * sKey) {
+    HKEY hKey;
+    JavaVersion * result = NULL;
+
+    if (RegOpenKeyExA(key,
+            sKey,
+            0,
+            KEY_READ,
+            &hKey) == ERROR_SUCCESS
+            ) {
+        DWORD retCode;
+        char achClass[MAX_PATH]; // buffer for class name
+        DWORD cchClassName = MAX_PATH; // size of class string
+
+
+        DWORD cchValue = MAX_VALUE_NAME;
+        DWORD cSubKeys = 0; // number of subkeys
+        DWORD cbMaxSubKey; // longest subkey size
+        DWORD cchMaxClass; // longest class string
+        DWORD cValues; // number of values for key
+        DWORD cchMaxValue; // longest value name
+        DWORD cbMaxValueData; // longest value data
+        DWORD cbSecurityDescriptor; // size of security descriptor
+        FILETIME ftLastWriteTime; // last write time
+
+        retCode = RegQueryInfoKeyA(
+                hKey, // key handle
+                achClass, // buffer for class name
+                &cchClassName, // size of class string
+                NULL, // reserved
+                &cSubKeys, // number of subkeys
+                &cbMaxSubKey, // longest subkey size
+                &cchMaxClass, // longest class string
+                &cValues, // number of values for this key
+                &cchMaxValue, // longest value name
+                &cbMaxValueData, // longest value data
+                &cbSecurityDescriptor, // security descriptor
+                &ftLastWriteTime); // last write time
+
+        if (cSubKeys) {
+            for (unsigned int i = 0; i < cSubKeys; i++) {
+                char achKey[MAX_KEY_LENGTH]; // buffer for subkey name
+                DWORD cbName = MAX_KEY_LENGTH;
+                retCode = RegEnumKeyExA(hKey, i,
+                        achKey,
+                        &cbName,
+                        NULL,
+                        NULL,
+                        NULL,
+                        &ftLastWriteTime);
+
+                if (retCode == ERROR_SUCCESS) {
+#ifdef _DEBUG
+                    cout << achKey << endl;
+#endif
+                    JavaVersion * nv = parseName(achKey);
+
+                    bool isHome = checkJavaHome(key, sKey, achKey, nv);
+#ifdef _DEBUG
+                    wcout << nv->home << " " << isHome << endl;
+#endif
+
+                    if (isHome)
+                    if (result == NULL) {
+                        result = nv;
+#ifdef _DEBUG
+                        cout << "NEW" << endl;
+#endif
+                    }
+                    else {
+                        if (nv != NULL) {
+                            if (*nv > *result) {
+#ifdef _DEBUG
+                                cout << "REPLACE" << endl;
+#endif
+                                delete result;
+                                result = nv;
+                            }
+                            else {
+#ifdef _DEBUG
+                                cout << "NO" << endl;
+#endif
+                                delete nv;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        RegCloseKey(hKey);
+    }
+
+    return result;
+}
+
+int fileExists(const std::wstring& path) {
+    WIN32_FIND_DATA ffd;
+    HANDLE hFind;
+
+    hFind = FindFirstFile(path.data(), &ffd);
+    if (hFind == INVALID_HANDLE_VALUE)
+        return FALSE;
+
+    FindClose(hFind);
+    return (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
+}
+
+bool hasEnding(std::wstring const &fullString, std::wstring const &ending) {
+    if (fullString.length() >= ending.length()) {
+        return (0 == fullString.compare(fullString.length() - ending.length(), 
+                                                        ending.length(), ending));
+    }
+    else {
+        return false;
+    }
+}
+
+std::wstring ExtractFilePath(std::wstring Path) {
+    std::wstring result;
+    size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
+    if (slash != std::wstring::npos)
+        result = Path.substr(0, slash);
+    return result;
+}
+
+std::wstring GetCurrentExecutableName() {
+    TCHAR FileName[MAX_PATH];
+    GetModuleFileName(NULL, FileName, MAX_PATH);
+    return FileName;
+}
+
+int wmain(int argc, wchar_t* argv[]) {
+    wchar_t buf[MAX_PATH];
+    GetModuleFileName(NULL, buf, MAX_PATH);
+
+    std::wstring javacmd;
+    std::wstring javahome;
+
+    std::wstring exe = GetCurrentExecutableName();
+
+    if (exe.length() <= 0) {
+        JavaVersion * jv2 = GetMaxVersion(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\JDK");
+        if (jv2 != NULL) {
+            javahome = jv2->home;
+            javacmd = javahome + L"\\bin\\" + L"\\java.exe";
+        }
+        else {
+            javacmd = L"java.exe";
+        }
+    } else {
+        javacmd = ExtractFilePath(exe) + L"\\java.exe";
+    }
+
+    std::wstring cmd = L"\"" + javacmd + L"\"";
+    if (javahome.length() > 0) {
+        SetEnvironmentVariable(L"JAVA_HOME", javahome.c_str());
+    }
+
+    std::wstring memory = L"-Xmx512M";
+    std::wstring debug = L"";
+    std::wstring args = L"";
+
+    for (int i = 1; i < argc; i++) {
+        std::wstring argument = argv[i];
+        std::wstring debug_arg = L"-J-Xdebug:";
+        std::wstring icon_swap_arg = L"--icon-swap";
+        std::wstring version_swap_arg = L"--version-swap";
+
+        if (argument.find(L"-J-Xmx", 0) == 0) {
+            memory = argument.substr(2, argument.length() - 2);
+        }
+        else if (argument.find(debug_arg, 0) == 0) {
+            std::wstring address = argument.substr(debug_arg.length(),
+                                argument.length() - debug_arg.length());
+            debug = L"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=" + address;
+        }
+        else if (argument.find(icon_swap_arg, 0) == 0) {
+            if (argc != 4) {
+                fwprintf(stderr, TEXT("Usage: jpackager.exe --icon-swap [Icon File Name] [Executable File Name]\n"));
+                return 1;
+            }
+
+            wprintf(L"Icon File Name: %s\n", argv[i + 1]);
+            wprintf(L"Executable File Name: %s\n", argv[i + 2]);
+
+            if (ChangeIcon(argv[i + 1], argv[i + 2]) == true) {
+                return 0;
+            }
+            else {
+                fwprintf(stderr, TEXT("failed\n"));
+                return 1;
+            }
+        }
+        else if (argument.find(version_swap_arg, 0) == 0) {
+            if (argc != 4) {
+                fwprintf(stderr, TEXT("Usage: jpackager.exe --version-swap [Property File Name] [Executable File Name]\n"));
+                return 1;
+            }
+
+            fwprintf(stdout, TEXT("Resource File Name: %s\n"), argv[i + 1]);
+            fwprintf(stdout, TEXT("Executable File Name: %s\n"), argv[i + 2]);
+
+            VersionInfoSwap vs(argv[i + 1], argv[i + 2]);
+
+            if (vs.PatchExecutable()) {
+                return 0;
+            }
+            else {
+                fwprintf(stderr, TEXT("failed\n"));
+                return 1;
+            }
+        }
+        else {
+            args = args + L" \"" + argv[i] + L"\"";
+        }
+    }
+
+
+    cmd += debug + L" " + memory +
+                L" -m jdk.packager/jdk.packager.Main" +
+                L" " + args;
+
+#ifdef _DEBUG
+    fwprintf (stdout, TEXT("%s"), cmd.c_str());
+#endif
+
+    STARTUPINFO start;
+    PROCESS_INFORMATION pi;
+    memset(&start, 0, sizeof (start));
+    start.cb = sizeof(start);
+
+    if (!CreateProcess(NULL, (wchar_t *) cmd.data(),
+            NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &start, &pi)) {
+#ifdef _DEBUG
+        fprintf(stderr, "Cannot start java.exe");
+#endif
+        return EXIT_FAILURE;
+    }
+
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    unsigned long exitCode;
+    GetExitCodeProcess(pi.hProcess, &exitCode);
+
+    CloseHandle(pi.hProcess);
+    CloseHandle(pi.hThread);
+
+    return exitCode;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/native/jpackager/javapackager.manifest	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+ <assemblyIdentity version="FXVERSION"
+         processorArchitecture="X86"
+         name="javapackager.exe"
+         type="win32"/>
+  <description>JavaFX application packager</description>
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+    <security>
+      <requestedPrivileges>
+        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+  <!-- Indicate this JDK version is Windows 7 compatible -->
+   <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+      <application>
+        <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+        <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+      </application>
+    </compatibility>
+</assembly>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/native/jpackager/javapackager.rc	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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"
+
+// Need 2 defines so macro argument to XSTR will get expanded before quoting.
+#define XSTR(x) STR(x)
+#define STR(x)  #x
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION    JFX_FVER
+ PRODUCTVERSION JFX_FVER
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ // FILEOS 0x4 is Win32, 0x40004 is Win32 NT only
+ FILEOS 0x4L
+ // FILETYPE should be 0x1 for .exe and 0x2 for .dll
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "000004b0"
+        BEGIN
+            VALUE "CompanyName",      XSTR(JFX_COMPANY)        "\0"
+            VALUE "FileDescription",  XSTR(JFX_COMPONENT)      "\0"
+            VALUE "FileVersion",      XSTR(JFX_VER)            "\0"
+            VALUE "Full Version",     XSTR(JFX_BUILD_ID)       "\0"
+            VALUE "InternalName",     XSTR(JFX_INTERNAL_NAME)  "\0"
+            VALUE "LegalCopyright",   XSTR(JFX_COPYRIGHT)      "\0"
+            VALUE "OriginalFilename", XSTR(JFX_FNAME)          "\0"
+            VALUE "ProductName",      XSTR(JFX_NAME)           "\0"
+            VALUE "ProductVersion",   XSTR(JFX_VER)            "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0, 1200
+    END
+END
+
+
+#define MANIFEST_RESOURCE_ID 1
+
+// Manifest
+//
+
+MANIFEST_RESOURCE_ID RT_MANIFEST "javapackager.manifest"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.packager/windows/native/launcher/WinLauncher.cpp	Mon Aug 27 16:02:55 2018 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+#include <Windows.h>
+#include <Shellapi.h>
+#include <locale.h>
+#include <tchar.h>
+#include <string>
+
+#define PACKAGER_LIBRARY TEXT("packager.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;
+}
+
+int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+                       LPTSTR lpCmdLine, int nCmdShow) {
+    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(PACKAGER_LIBRARY);
+
+    if (library == NULL) {
+        std::wstring title = GetTitle();
+        std::wstring description = std::wstring(PACKAGER_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(argc, argv) == true) {
+            result = 0;
+
+            if (stop != NULL) {
+                stop();
+            }
+        }
+
+        ::FreeLibrary(library);
+    }
+
+    if (argv != NULL) {
+        LocalFree(argv);
+    }
+
+    return result;
+}
+