8213324:jpackager deletes existing app directory without warning JDK-8200758-branch
authorherrick
Thu, 08 Nov 2018 13:46:28 -0500
branchJDK-8200758-branch
changeset 57021 441c020bf626
parent 57020 a828547f7e50
child 57022 81021f910bc2
8213324:jpackager deletes existing app directory without warning Reviewed-by: almatvee, kcr
src/jdk.jpackager/linux/classes/jdk/jpackager/internal/linux/LinuxAppBundler.java
src/jdk.jpackager/linux/classes/jdk/jpackager/internal/resources/linux/LinuxAppBundler.properties
src/jdk.jpackager/linux/classes/jdk/jpackager/internal/resources/linux/LinuxAppBundler_ja.properties
src/jdk.jpackager/linux/classes/jdk/jpackager/internal/resources/linux/LinuxAppBundler_zh_CN.properties
src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/mac/MacAppBundler.java
src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/resources/mac/MacAppBundler.properties
src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/resources/mac/MacAppBundler_ja.properties
src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/resources/mac/MacAppBundler_zh_CN.properties
src/jdk.jpackager/share/classes/jdk/jpackager/internal/AbstractImageBundler.java
src/jdk.jpackager/share/classes/jdk/jpackager/internal/Arguments.java
src/jdk.jpackager/share/classes/jdk/jpackager/internal/StandardBundlerParam.java
src/jdk.jpackager/share/classes/jdk/jpackager/internal/ValidOptions.java
src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/AbstractImageBundler.properties
src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/AbstractImageBundler_ja.properties
src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/AbstractImageBundler_zh_CN.properties
src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/CLIHelp.properties
src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/CLIHelpi_ja.properties
src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/CLIHelpi_zh_CN.properties
src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/StandardBundlerParam.properties
src/jdk.jpackager/windows/classes/jdk/jpackager/internal/builders/windows/WindowsAppImageBuilder.java
src/jdk.jpackager/windows/classes/jdk/jpackager/internal/resources/windows/WinAppBundler.properties
src/jdk.jpackager/windows/classes/jdk/jpackager/internal/resources/windows/WinAppBundler_ja.properties
src/jdk.jpackager/windows/classes/jdk/jpackager/internal/resources/windows/WinAppBundler_zh_CN.properties
src/jdk.jpackager/windows/classes/jdk/jpackager/internal/windows/WinAppBundler.java
--- a/src/jdk.jpackager/linux/classes/jdk/jpackager/internal/linux/LinuxAppBundler.java	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/linux/classes/jdk/jpackager/internal/linux/LinuxAppBundler.java	Thu Nov 08 13:46:28 2018 -0500
@@ -162,7 +162,8 @@
     private File doJreBundle(Map<String, ? super Object> p,
             File outputDirectory, boolean dependentTask) {
         try {
-            File rootDirectory = createRoot(p, outputDirectory, dependentTask);
+            File rootDirectory = createRoot(p, outputDirectory, dependentTask,
+                    APP_FS_NAME.fetchFrom(p), "linuxapp-image-builder");
             AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder(
                     APP_NAME.fetchFrom(p), outputDirectory.toPath());
             File predefined = PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
@@ -182,7 +183,8 @@
     private File doAppBundle(Map<String, ? super Object> p,
             File outputDirectory, boolean dependentTask) {
         try {
-            File rootDirectory = createRoot(p, outputDirectory, dependentTask);
+            File rootDirectory = createRoot(p, outputDirectory, dependentTask,
+                    APP_FS_NAME.fetchFrom(p), "linuxapp-image-builder");
             AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder(p,
                     outputDirectory.toPath());
             if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {
@@ -198,38 +200,6 @@
         }
     }
 
-    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.verbose(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");
--- a/src/jdk.jpackager/linux/classes/jdk/jpackager/internal/resources/linux/LinuxAppBundler.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/linux/classes/jdk/jpackager/internal/resources/linux/LinuxAppBundler.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -40,8 +40,4 @@
 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.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.
--- a/src/jdk.jpackager/linux/classes/jdk/jpackager/internal/resources/linux/LinuxAppBundler_ja.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/linux/classes/jdk/jpackager/internal/resources/linux/LinuxAppBundler_ja.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -40,8 +40,5 @@
 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.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
--- a/src/jdk.jpackager/linux/classes/jdk/jpackager/internal/resources/linux/LinuxAppBundler_zh_CN.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/linux/classes/jdk/jpackager/internal/resources/linux/LinuxAppBundler_zh_CN.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -40,8 +40,5 @@
 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.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
--- a/src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/mac/MacAppBundler.java	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/mac/MacAppBundler.java	Thu Nov 08 13:46:28 2018 -0500
@@ -365,7 +365,7 @@
             File outputDirectory, boolean dependentTask) {
         try {
             File rootDirectory = createRoot(p, outputDirectory, dependentTask,
-                    APP_NAME.fetchFrom(p));
+                    APP_NAME.fetchFrom(p), "macapp-image-builder");
             AbstractAppImageBuilder appBuilder = new MacAppImageBuilder(p,
                     APP_NAME.fetchFrom(p), outputDirectory.toPath());
             File predefined = PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
@@ -386,7 +386,7 @@
             boolean dependentTask) {
         try {
             File rootDirectory = createRoot(p, outputDirectory, dependentTask,
-                    APP_NAME.fetchFrom(p) + ".app");
+                    APP_NAME.fetchFrom(p) + ".app", "macapp-image-builder");
             AbstractAppImageBuilder appBuilder =
                     new MacAppImageBuilder(p, outputDirectory.toPath());
             if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {
@@ -402,38 +402,6 @@
         }
     }
 
-    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.verbose(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) {
         if (CONFIG_ROOT.fetchFrom(params) != null) {
             getConfig_Icon(params).delete();
--- a/src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/resources/mac/MacAppBundler.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/resources/mac/MacAppBundler.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -60,8 +60,6 @@
 param.default-icon-icns=Default Icon
 param.default-icon-icns.description=The Default Icon for when a user does not specify an icns file.
 
-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.
@@ -74,7 +72,6 @@
 
 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.
--- a/src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/resources/mac/MacAppBundler_ja.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/resources/mac/MacAppBundler_ja.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -34,8 +34,6 @@
 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
 
-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
@@ -48,7 +46,6 @@
 
 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
--- a/src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/resources/mac/MacAppBundler_zh_CN.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/macosx/classes/jdk/jpackager/internal/resources/mac/MacAppBundler_zh_CN.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -60,8 +60,6 @@
 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
 
-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
@@ -74,7 +72,6 @@
 
 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
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/AbstractImageBundler.java	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/AbstractImageBundler.java	Thu Nov 08 13:46:28 2018 -0500
@@ -30,6 +30,8 @@
 import java.util.ResourceBundle;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.io.File;
+import java.io.IOException;
 
 import static jdk.jpackager.internal.StandardBundlerParam.*;
 
@@ -117,4 +119,44 @@
             }
         }
     }
+
+    protected File createRoot(Map<String, ? super Object> p,
+            File outputDirectory, boolean dependentTask,
+            String name, String jlinkKey) 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.verbose(MessageFormat.format(
+                    I18N.getString("message.creating-app-bundle"),
+                    name, outputDirectory.getAbsolutePath()));
+        }
+
+        // Create directory structure
+        File rootDirectory = new File(outputDirectory, name);
+
+        if (rootDirectory.exists()) {
+            if (!(FORCE.fetchFrom(p))) {
+                throw new IOException(MessageFormat.format(
+                        I18N.getString("error.root-exists-without-force"),
+                        rootDirectory.getAbsolutePath()));
+            }
+            IOUtils.deleteRecursive(rootDirectory);
+        }
+        rootDirectory.mkdirs();
+
+        if (!p.containsKey(JLinkBundlerHelper.JLINK_BUILDER.getID())) {
+            p.put(JLinkBundlerHelper.JLINK_BUILDER.getID(), jlinkKey);
+        }
+
+        return rootDirectory;
+    }
+
 }
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/Arguments.java	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/Arguments.java	Thu Nov 08 13:46:28 2018 -0500
@@ -229,6 +229,11 @@
             Log.setVerbose(true);
         }),
 
+        FORCE ("force", OptionCategories.PROPERTY, () -> {
+            setOptionValue("force", true);
+        }),
+
+
         FILES ("files", "f", OptionCategories.PROPERTY, () -> {
               context().files = new ArrayList<>();
               String files = popArg();
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/StandardBundlerParam.java	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/StandardBundlerParam.java	Thu Nov 08 13:46:28 2018 -0500
@@ -419,6 +419,18 @@
                             true : Boolean.valueOf(s)
             );
 
+    public static final StandardBundlerParam<Boolean> FORCE  =
+            new StandardBundlerParam<>(
+                    I18N.getString("param.force.name"),
+                    I18N.getString("param.force.description"),
+                    Arguments.CLIOptions.FORCE.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"),
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/ValidOptions.java	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/ValidOptions.java	Thu Nov 08 13:46:28 2018 -0500
@@ -66,6 +66,7 @@
         add(CLIOptions.CREATE_IMAGE, CLIOptions.NAME);
         add(CLIOptions.CREATE_IMAGE, CLIOptions.IDENTIFIER);
         add(CLIOptions.CREATE_IMAGE, CLIOptions.VERBOSE);
+        add(CLIOptions.CREATE_IMAGE, CLIOptions.FORCE);
         add(CLIOptions.CREATE_IMAGE, CLIOptions.FILES);
         add(CLIOptions.CREATE_IMAGE, CLIOptions.ARGUMENTS);
         add(CLIOptions.CREATE_IMAGE, CLIOptions.STRIP_NATIVE_COMMANDS);
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/AbstractImageBundler.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/AbstractImageBundler.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -24,6 +24,12 @@
 #
 #
 
+message.creating-app-bundle=Creating app bundle\: {0} in {1}
+
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+error.root-exists-without-force=Root Directory {0} already exists and --force is not specified"
+
 error.no-application-class=Main application class is missing.
 error.no-application-class.advice=Please specify main application class.
 
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/AbstractImageBundler_ja.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/AbstractImageBundler_ja.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -23,6 +23,15 @@
 # questions.
 #
 #
+message.creating-app-bundle=Creating app bundle\: {0} in {1}
+
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+error.root-exists-without-force=Root Directory {0} already exists and --force is not specified"
+
+error.no-application-class=Main application class is missing.
+error.no-application-class.advice=Please specify main application class.
+
 
 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
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/AbstractImageBundler_zh_CN.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/AbstractImageBundler_zh_CN.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -23,6 +23,14 @@
 # questions.
 #
 #
+message.creating-app-bundle=Creating app bundle\: {0} in {1}
+
+error.cannot-create-output-dir=Output directory {0} cannot be created.
+error.cannot-write-to-output-dir=Output directory {0} is not writable.
+error.root-exists-without-force=Root Directory {0} already exists and --force is not specified"
+
+error.no-application-class=Main application class is missing.
+error.no-application-class.advice=Please specify main application class.
 
 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
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/CLIHelp.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/CLIHelp.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -121,6 +121,7 @@
 \          Category or group of the application.\n\
 \  --vendor <vendor string>\n\
 \          Vendor of the application.\n\
+\  --force -- Allow the deletion of any existing output root directory when creating an Application image.\n\
 \n\
 Modular options:\n\
 \  --module -m <module name>\n\
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/CLIHelpi_ja.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/CLIHelpi_ja.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -121,6 +121,7 @@
 \          Category or group of the application.\n\
 \  --vendor <vendor string>\n\
 \          Vendor of the application.\n\
+\  --force -- Allow the deletion of any existing output root directory when creating an Application image.\n\
 \n\
 Modular options:\n\
 \  --module -m <module name>\n\
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/CLIHelpi_zh_CN.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/CLIHelpi_zh_CN.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -121,6 +121,7 @@
 \          Category or group of the application.\n\
 \  --vendor <vendor string>\n\
 \          Vendor of the application.\n\
+\  --force -- Allow the deletion of any existing output root directory when creating an Application image.\n\
 \n\
 Modular options:\n\
 \  --module -m <module name>\n\
--- a/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/StandardBundlerParam.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/share/classes/jdk/jpackager/internal/resources/StandardBundlerParam.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -110,6 +110,9 @@
 param.verbose.name=Verbose
 param.verbose.description=Flag to print out more information and saves configuration files for bundlers.
 
+param.force.name=Force
+param.force.description=Flag to allow removal of existing Build Root contents
+
 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.
 
--- a/src/jdk.jpackager/windows/classes/jdk/jpackager/internal/builders/windows/WindowsAppImageBuilder.java	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/windows/classes/jdk/jpackager/internal/builders/windows/WindowsAppImageBuilder.java	Thu Nov 08 13:46:28 2018 -0500
@@ -213,12 +213,6 @@
         }
     }
 
-    // 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";
     }
--- a/src/jdk.jpackager/windows/classes/jdk/jpackager/internal/resources/windows/WinAppBundler.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/windows/classes/jdk/jpackager/internal/resources/windows/WinAppBundler.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -47,11 +47,8 @@
 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.
 error.cannot-find-launcher=Cannot find cfg file in predefined app image directory {0}.
 
-message.creating-app-bundle=Creating app bundle\: {0} in {1}
 message.result-dir=Result application bundle\: {0}
 message.disable-bit-architecture-check=Disabled check for bit architecture mismatch.
 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.
--- a/src/jdk.jpackager/windows/classes/jdk/jpackager/internal/resources/windows/WinAppBundler_ja.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/windows/classes/jdk/jpackager/internal/resources/windows/WinAppBundler_ja.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -47,11 +47,8 @@
 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
 error.cannot-find-launcher=Cannot find cfg file in predefined app image directory {0}.
 
-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.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.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
--- a/src/jdk.jpackager/windows/classes/jdk/jpackager/internal/resources/windows/WinAppBundler_zh_CN.properties	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/windows/classes/jdk/jpackager/internal/resources/windows/WinAppBundler_zh_CN.properties	Thu Nov 08 13:46:28 2018 -0500
@@ -47,11 +47,8 @@
 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
 error.cannot-find-launcher=Cannot find cfg file in predefined app image directory {0}.
 
-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.disable-bit-architecture-check=\u5DF2\u7981\u7528\u4F4D\u4F53\u7CFB\u7ED3\u6784\u4E0D\u5339\u914D\u68C0\u67E5\u3002
 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
--- a/src/jdk.jpackager/windows/classes/jdk/jpackager/internal/windows/WinAppBundler.java	Thu Nov 08 10:56:28 2018 -0500
+++ b/src/jdk.jpackager/windows/classes/jdk/jpackager/internal/windows/WinAppBundler.java	Thu Nov 08 13:46:28 2018 -0500
@@ -147,12 +147,6 @@
         }
     }
 
-    // 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));
-    }
-
     private static boolean usePredefineAppName(Map<String, ? super Object> p) {
         return (PREDEFINED_APP_IMAGE.fetchFrom(p) != null);
     }
@@ -206,37 +200,6 @@
         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.verbose(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)) {
@@ -249,7 +212,8 @@
     File doJreBundle(Map<String, ? super Object> p,
             File outputDirectory, boolean dependentTask) {
         try {
-            File rootDirectory = createRoot(p, outputDirectory, dependentTask);
+            File rootDirectory = createRoot(p, outputDirectory, dependentTask,
+                APP_NAME.fetchFrom(p), "windowsapp-image-builder");
             AbstractAppImageBuilder appBuilder = new WindowsAppImageBuilder(
                     APP_NAME.fetchFrom(p),
                     outputDirectory.toPath());
@@ -270,8 +234,8 @@
     File doAppBundle(Map<String, ? super Object> p,
             File outputDirectory, boolean dependentTask) {
         try {
-            File rootDirectory =
-                    createRoot(p, outputDirectory, dependentTask);
+            File rootDirectory = createRoot(p, outputDirectory, dependentTask,
+                    APP_NAME.fetchFrom(p), "windowsapp-image-builder");
             AbstractAppImageBuilder appBuilder =
                     new WindowsAppImageBuilder(p, outputDirectory.toPath());
             if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {