--- old/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java 2020-02-26 17:47:28.305674200 -0500 +++ new/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java 2020-02-26 17:47:25.622419400 -0500 @@ -111,7 +111,15 @@ return identifier; } - return IDENTIFIER.fetchFrom(params); + identifier = IDENTIFIER.fetchFrom(params); + if (identifier != null) { + return identifier; + } + // the IDENTIFIER (above) will default to derive from + // the main-class, in case there is no main-class + // (such as runtime installer) revert to the name. + // any of these could be invalid, so check later. + return APP_NAME.fetchFrom(params); }, (s, p) -> s); --- old/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacPkgBundler.java 2020-02-26 17:47:47.693426000 -0500 +++ new/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacPkgBundler.java 2020-02-26 17:47:45.252803900 -0500 @@ -510,22 +510,43 @@ return "pkg"; } + private static boolean isValidBundleIdentifier(String id) { + for (int i = 0; i < id.length(); i++) { + char a = id.charAt(i); + // We check for ASCII codes first which we accept. If check fails, + // check if it is acceptable extended ASCII or unicode character. + if ((a >= 'A' && a <= 'Z') || (a >= 'a' && a <= 'z') + || (a >= '0' && a <= '9') || (a == '-' || a == '.')) { + continue; + } + return false; + } + return true; + } + @Override public boolean validate(Map params) throws ConfigException { try { Objects.requireNonNull(params); - // run basic validation to ensure requirements are met + // run basic validation to ensure requirements are met // we are not interested in return code, only possible exception validateAppImageAndBundeler(params); - if (MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) == null) { + String identifier = MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params); + if (identifier == null) { throw new ConfigException( I18N.getString("message.app-image-requires-identifier"), I18N.getString( "message.app-image-requires-identifier.advice")); } + if (!isValidBundleIdentifier(identifier)) { + throw new ConfigException( + MessageFormat.format(I18N.getString( + "message.invalid-identifier"), identifier), + I18N.getString("message.invalid-identifier.advice")); + } // reject explicitly set sign to true and no valid signature key if (Optional.ofNullable(MacAppImageBuilder. --- old/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacResources.properties 2020-02-26 17:48:04.379839700 -0500 +++ new/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/resources/MacResources.properties 2020-02-26 17:48:02.312837200 -0500 @@ -76,6 +76,8 @@ message.app-image-requires-app-name.advice=Set the app name via the -name CLI flag, the fx:application/@name ANT attribute, or via the 'appName' bundler argument. message.app-image-requires-identifier=Unable to extract identifier from app image. message.app-image-requires-identifier.advice=Use "--verbose" for extended error message or specify it via "--mac-package-identifier". +message.invalid-identifier=invalid mac bundle identifier [{0}]. +message.invalid-identifier.advice=specify identifier with "--mac-package-identifier". message.building-dmg=Building DMG package for {0}. message.running-script=Running shell script on application image [{0}]. message.preparing-dmg-setup=Preparing dmg setup: {0}.