< prev index next >

src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java

Print this page




  30 import java.math.BigInteger;
  31 import java.text.MessageFormat;
  32 import java.util.Arrays;
  33 import java.util.Collection;
  34 import java.util.HashMap;
  35 import java.util.Map;
  36 import java.util.Optional;
  37 import java.util.ResourceBundle;
  38 
  39 import static jdk.jpackage.internal.StandardBundlerParam.*;
  40 import static jdk.jpackage.internal.MacBaseInstallerBundler.*;
  41 import jdk.jpackage.internal.AbstractAppImageBuilder;
  42 
  43 public class MacAppBundler extends AbstractImageBundler {
  44 
  45     private static final ResourceBundle I18N = ResourceBundle.getBundle(
  46             "jdk.jpackage.internal.resources.MacResources");
  47 
  48     private static final String TEMPLATE_BUNDLE_ICON = "GenericApp.icns";
  49 
  50     private static Map<String, String> getMacCategories() {
  51         Map<String, String> map = new HashMap<>();
  52         map.put("Business", "public.app-category.business");
  53         map.put("Developer Tools", "public.app-category.developer-tools");
  54         map.put("Education", "public.app-category.education");
  55         map.put("Entertainment", "public.app-category.entertainment");
  56         map.put("Finance", "public.app-category.finance");
  57         map.put("Games", "public.app-category.games");
  58         map.put("Graphics & Design", "public.app-category.graphics-design");
  59         map.put("Healthcare & Fitness",
  60                 "public.app-category.healthcare-fitness");
  61         map.put("Lifestyle", "public.app-category.lifestyle");
  62         map.put("Medical", "public.app-category.medical");
  63         map.put("Music", "public.app-category.music");
  64         map.put("News", "public.app-category.news");
  65         map.put("Photography", "public.app-category.photography");
  66         map.put("Productivity", "public.app-category.productivity");
  67         map.put("Reference", "public.app-category.reference");
  68         map.put("Social Networking", "public.app-category.social-networking");
  69         map.put("Sports", "public.app-category.sports");
  70         map.put("Travel", "public.app-category.travel");


  80         map.put("Casino Games", "public.app-category.casino-games");
  81         map.put("Dice Games", "public.app-category.dice-games");
  82         map.put("Educational Games", "public.app-category.educational-games");
  83         map.put("Family Games", "public.app-category.family-games");
  84         map.put("Kids Games", "public.app-category.kids-games");
  85         map.put("Music Games", "public.app-category.music-games");
  86         map.put("Puzzle Games", "public.app-category.puzzle-games");
  87         map.put("Racing Games", "public.app-category.racing-games");
  88         map.put("Role Playing Games", "public.app-category.role-playing-games");
  89         map.put("Simulation Games", "public.app-category.simulation-games");
  90         map.put("Sports Games", "public.app-category.sports-games");
  91         map.put("Strategy Games", "public.app-category.strategy-games");
  92         map.put("Trivia Games", "public.app-category.trivia-games");
  93         map.put("Word Games", "public.app-category.word-games");
  94 
  95         return map;
  96     }
  97 
  98     public static final EnumeratedBundlerParam<String> MAC_CATEGORY =
  99             new EnumeratedBundlerParam<>(
 100                     I18N.getString("param.category-name"),
 101                     I18N.getString("param.category-name.description"),
 102                     Arguments.CLIOptions.MAC_APP_STORE_CATEGORY.getId(),
 103                     String.class,
 104                     params -> params.containsKey(CATEGORY.getID())
 105                             ? CATEGORY.fetchFrom(params)
 106                             : "Unknown",
 107                     (s, p) -> s,
 108                     getMacCategories(),
 109                     false //strict - for MacStoreBundler this should be strict
 110             );
 111 
 112     public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME =
 113             new StandardBundlerParam<>(
 114                     I18N.getString("param.cfbundle-name.name"),
 115                     I18N.getString("param.cfbundle-name.description"),
 116                     Arguments.CLIOptions.MAC_BUNDLE_NAME.getId(),
 117                     String.class,
 118                     params -> null,
 119                     (s, p) -> s);
 120 
 121     public static final BundlerParamInfo<String> MAC_CF_BUNDLE_IDENTIFIER =
 122             new StandardBundlerParam<>(
 123                     I18N.getString("param.cfbundle-identifier.name"),
 124                     I18N.getString("param.cfbundle-identifier.description"),
 125                     Arguments.CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(),
 126                     String.class,
 127                     IDENTIFIER::fetchFrom,
 128                     (s, p) -> s);
 129 
 130     public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION =
 131             new StandardBundlerParam<>(
 132                     I18N.getString("param.cfbundle-version.name"),
 133                     I18N.getString("param.cfbundle-version.description"),
 134                     "mac.CFBundleVersion",
 135                     String.class,
 136                     p -> {
 137                         String s = VERSION.fetchFrom(p);
 138                         if (validCFBundleVersion(s)) {
 139                             return s;
 140                         } else {
 141                             return "100";
 142                         }
 143                     },
 144                     (s, p) -> s);
 145 
 146     public static final BundlerParamInfo<String> DEFAULT_ICNS_ICON =
 147             new StandardBundlerParam<>(
 148             I18N.getString("param.default-icon-icns"),
 149             I18N.getString("param.default-icon-icns.description"),
 150             ".mac.default.icns",
 151             String.class,
 152             params -> TEMPLATE_BUNDLE_ICON,
 153             (s, p) -> s);
 154 
 155     public static final BundlerParamInfo<String> DEVELOPER_ID_APP_SIGNING_KEY =
 156             new StandardBundlerParam<>(
 157             I18N.getString("param.signing-key-developer-id-app.name"),
 158             I18N.getString("param.signing-key-developer-id-app.description"),
 159             "mac.signing-key-developer-id-app",
 160             String.class,
 161             params -> {
 162                     String result = MacBaseInstallerBundler.findKey(
 163                             "Developer ID Application: "
 164                             + SIGNING_KEY_USER.fetchFrom(params),
 165                             SIGNING_KEYCHAIN.fetchFrom(params),
 166                             VERBOSE.fetchFrom(params));
 167                     if (result != null) {
 168                         MacCertificate certificate = new MacCertificate(result,
 169                                 VERBOSE.fetchFrom(params));
 170 
 171                         if (!certificate.isValid()) {
 172                             Log.error(MessageFormat.format(I18N.getString(
 173                                     "error.certificate.expired"), result));
 174                         }
 175                     }
 176 
 177                     return result;
 178                 },
 179             (s, p) -> s);
 180 
 181     public static final BundlerParamInfo<String> BUNDLE_ID_SIGNING_PREFIX =
 182             new StandardBundlerParam<>(
 183             I18N.getString("param.bundle-id-signing-prefix.name"),
 184             I18N.getString("param.bundle-id-signing-prefix.description"),
 185             Arguments.CLIOptions.MAC_BUNDLE_SIGNING_PREFIX.getId(),
 186             String.class,
 187             params -> IDENTIFIER.fetchFrom(params) + ".",
 188             (s, p) -> s);
 189 
 190     public static final BundlerParamInfo<File> ICON_ICNS =
 191             new StandardBundlerParam<>(
 192             I18N.getString("param.icon-icns.name"),
 193             I18N.getString("param.icon-icns.description"),
 194             "icon.icns",
 195             File.class,
 196             params -> {
 197                 File f = ICON.fetchFrom(params);
 198                 if (f != null && !f.getName().toLowerCase().endsWith(".icns")) {
 199                     Log.error(MessageFormat.format(
 200                             I18N.getString("message.icon-not-icns"), f));
 201                     return null;
 202                 }
 203                 return f;
 204             },
 205             (s, p) -> new File(s));
 206 
 207     public static boolean validCFBundleVersion(String v) {
 208         // CFBundleVersion (String - iOS, OS X) specifies the build version
 209         // number of the bundle, which identifies an iteration (released or
 210         // unreleased) of the bundle. The build version number should be a
 211         // string comprised of three non-negative, period-separated integers
 212         // with the first integer being greater than zero. The string should
 213         // only contain numeric (0-9) and period (.) characters. Leading zeros


 289                     I18N.getString("error.invalid-cfbundle-version"),
 290                     I18N.getString("error.invalid-cfbundle-version.advice"));
 291         }
 292 
 293         // reject explicitly set sign to true and no valid signature key
 294         if (Optional.ofNullable(MacAppImageBuilder.
 295                     SIGN_BUNDLE.fetchFrom(p)).orElse(Boolean.FALSE)) {
 296             String signingIdentity = DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(p);
 297             if (signingIdentity == null) {
 298                 throw new ConfigException(
 299                         I18N.getString("error.explicit-sign-no-cert"),
 300                         I18N.getString("error.explicit-sign-no-cert.advice"));
 301             }
 302         }
 303 
 304         return true;
 305     }
 306 
 307     File doBundle(Map<String, ? super Object> p, File outputDirectory,
 308             boolean dependentTask) throws PackagerException {
 309         if (RUNTIME_INSTALLER.fetchFrom(p)) {
 310             return doJreBundle(p, outputDirectory, dependentTask);
 311         } else {
 312             return doAppBundle(p, outputDirectory, dependentTask);
 313         }
 314     }
 315 
 316     File doJreBundle(Map<String, ? super Object> p, File outputDirectory,
 317             boolean dependentTask) throws PackagerException {
 318         try {
 319             File rootDirectory = createRoot(p, outputDirectory, dependentTask,
 320                     APP_NAME.fetchFrom(p), "macapp-image-builder");
 321             AbstractAppImageBuilder appBuilder = new MacAppImageBuilder(p,
 322                     APP_NAME.fetchFrom(p), outputDirectory.toPath());
 323             File predefined = PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
 324             if (predefined == null ) {
 325                 JLinkBundlerHelper.generateJre(p, appBuilder);
 326             } else {
 327                 return predefined;
 328             }
 329             return rootDirectory;
 330         } catch (PackagerException pe) {
 331             throw pe;
 332         } catch (Exception ex) {
 333             Log.verbose(ex);
 334             throw new PackagerException(ex);
 335         }
 336     }
 337 
 338     File doAppBundle(Map<String, ? super Object> p, File outputDirectory,
 339             boolean dependentTask) throws PackagerException {
 340         try {
 341             File rootDirectory = createRoot(p, outputDirectory, dependentTask,
 342                     APP_NAME.fetchFrom(p) + ".app", "macapp-image-builder");
 343             AbstractAppImageBuilder appBuilder =
 344                     new MacAppImageBuilder(p, outputDirectory.toPath());
 345             if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {
 346                 JLinkBundlerHelper.execute(p, appBuilder);
 347             } else {
 348                 StandardBundlerParam.copyPredefinedRuntimeImage(p, appBuilder);
 349             }
 350             return rootDirectory;
 351         } catch (PackagerException pe) {
 352             throw pe;
 353         } catch (Exception ex) {
 354             Log.verbose(ex);
 355             throw new PackagerException(ex);
 356         }
 357     }
 358 
 359     /////////////////////////////////////////////////////////////////////////
 360     // Implement Bundler
 361     /////////////////////////////////////////////////////////////////////////
 362 




  30 import java.math.BigInteger;
  31 import java.text.MessageFormat;
  32 import java.util.Arrays;
  33 import java.util.Collection;
  34 import java.util.HashMap;
  35 import java.util.Map;
  36 import java.util.Optional;
  37 import java.util.ResourceBundle;
  38 
  39 import static jdk.jpackage.internal.StandardBundlerParam.*;
  40 import static jdk.jpackage.internal.MacBaseInstallerBundler.*;
  41 import jdk.jpackage.internal.AbstractAppImageBuilder;
  42 
  43 public class MacAppBundler extends AbstractImageBundler {
  44 
  45     private static final ResourceBundle I18N = ResourceBundle.getBundle(
  46             "jdk.jpackage.internal.resources.MacResources");
  47 
  48     private static final String TEMPLATE_BUNDLE_ICON = "GenericApp.icns";
  49 
  50     public static Map<String, String> getMacCategories() {
  51         Map<String, String> map = new HashMap<>();
  52         map.put("Business", "public.app-category.business");
  53         map.put("Developer Tools", "public.app-category.developer-tools");
  54         map.put("Education", "public.app-category.education");
  55         map.put("Entertainment", "public.app-category.entertainment");
  56         map.put("Finance", "public.app-category.finance");
  57         map.put("Games", "public.app-category.games");
  58         map.put("Graphics & Design", "public.app-category.graphics-design");
  59         map.put("Healthcare & Fitness",
  60                 "public.app-category.healthcare-fitness");
  61         map.put("Lifestyle", "public.app-category.lifestyle");
  62         map.put("Medical", "public.app-category.medical");
  63         map.put("Music", "public.app-category.music");
  64         map.put("News", "public.app-category.news");
  65         map.put("Photography", "public.app-category.photography");
  66         map.put("Productivity", "public.app-category.productivity");
  67         map.put("Reference", "public.app-category.reference");
  68         map.put("Social Networking", "public.app-category.social-networking");
  69         map.put("Sports", "public.app-category.sports");
  70         map.put("Travel", "public.app-category.travel");


  80         map.put("Casino Games", "public.app-category.casino-games");
  81         map.put("Dice Games", "public.app-category.dice-games");
  82         map.put("Educational Games", "public.app-category.educational-games");
  83         map.put("Family Games", "public.app-category.family-games");
  84         map.put("Kids Games", "public.app-category.kids-games");
  85         map.put("Music Games", "public.app-category.music-games");
  86         map.put("Puzzle Games", "public.app-category.puzzle-games");
  87         map.put("Racing Games", "public.app-category.racing-games");
  88         map.put("Role Playing Games", "public.app-category.role-playing-games");
  89         map.put("Simulation Games", "public.app-category.simulation-games");
  90         map.put("Sports Games", "public.app-category.sports-games");
  91         map.put("Strategy Games", "public.app-category.strategy-games");
  92         map.put("Trivia Games", "public.app-category.trivia-games");
  93         map.put("Word Games", "public.app-category.word-games");
  94 
  95         return map;
  96     }
  97 
  98     public static final EnumeratedBundlerParam<String> MAC_CATEGORY =
  99             new EnumeratedBundlerParam<>(


 100                     Arguments.CLIOptions.MAC_APP_STORE_CATEGORY.getId(),
 101                     String.class,
 102                     params -> "Unknown",


 103                     (s, p) -> s,
 104                     getMacCategories(),
 105                     false //strict - for MacStoreBundler this should be strict
 106             );
 107 
 108     public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME =
 109             new StandardBundlerParam<>(


 110                     Arguments.CLIOptions.MAC_BUNDLE_NAME.getId(),
 111                     String.class,
 112                     params -> null,
 113                     (s, p) -> s);
 114 
 115     public static final BundlerParamInfo<String> MAC_CF_BUNDLE_IDENTIFIER =
 116             new StandardBundlerParam<>(


 117                     Arguments.CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(),
 118                     String.class,
 119                     IDENTIFIER::fetchFrom,
 120                     (s, p) -> s);
 121 
 122     public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION =
 123             new StandardBundlerParam<>(


 124                     "mac.CFBundleVersion",
 125                     String.class,
 126                     p -> {
 127                         String s = VERSION.fetchFrom(p);
 128                         if (validCFBundleVersion(s)) {
 129                             return s;
 130                         } else {
 131                             return "100";
 132                         }
 133                     },
 134                     (s, p) -> s);
 135 
 136     public static final BundlerParamInfo<String> DEFAULT_ICNS_ICON =
 137             new StandardBundlerParam<>(


 138             ".mac.default.icns",
 139             String.class,
 140             params -> TEMPLATE_BUNDLE_ICON,
 141             (s, p) -> s);
 142 
 143     public static final BundlerParamInfo<String> DEVELOPER_ID_APP_SIGNING_KEY =
 144             new StandardBundlerParam<>(


 145             "mac.signing-key-developer-id-app",
 146             String.class,
 147             params -> {
 148                     String result = MacBaseInstallerBundler.findKey(
 149                             "Developer ID Application: "
 150                             + SIGNING_KEY_USER.fetchFrom(params),
 151                             SIGNING_KEYCHAIN.fetchFrom(params),
 152                             VERBOSE.fetchFrom(params));
 153                     if (result != null) {
 154                         MacCertificate certificate = new MacCertificate(result,
 155                                 VERBOSE.fetchFrom(params));
 156 
 157                         if (!certificate.isValid()) {
 158                             Log.error(MessageFormat.format(I18N.getString(
 159                                     "error.certificate.expired"), result));
 160                         }
 161                     }
 162 
 163                     return result;
 164                 },
 165             (s, p) -> s);
 166 
 167     public static final BundlerParamInfo<String> BUNDLE_ID_SIGNING_PREFIX =
 168             new StandardBundlerParam<>(


 169             Arguments.CLIOptions.MAC_BUNDLE_SIGNING_PREFIX.getId(),
 170             String.class,
 171             params -> IDENTIFIER.fetchFrom(params) + ".",
 172             (s, p) -> s);
 173 
 174     public static final BundlerParamInfo<File> ICON_ICNS =
 175             new StandardBundlerParam<>(


 176             "icon.icns",
 177             File.class,
 178             params -> {
 179                 File f = ICON.fetchFrom(params);
 180                 if (f != null && !f.getName().toLowerCase().endsWith(".icns")) {
 181                     Log.error(MessageFormat.format(
 182                             I18N.getString("message.icon-not-icns"), f));
 183                     return null;
 184                 }
 185                 return f;
 186             },
 187             (s, p) -> new File(s));
 188 
 189     public static boolean validCFBundleVersion(String v) {
 190         // CFBundleVersion (String - iOS, OS X) specifies the build version
 191         // number of the bundle, which identifies an iteration (released or
 192         // unreleased) of the bundle. The build version number should be a
 193         // string comprised of three non-negative, period-separated integers
 194         // with the first integer being greater than zero. The string should
 195         // only contain numeric (0-9) and period (.) characters. Leading zeros


 271                     I18N.getString("error.invalid-cfbundle-version"),
 272                     I18N.getString("error.invalid-cfbundle-version.advice"));
 273         }
 274 
 275         // reject explicitly set sign to true and no valid signature key
 276         if (Optional.ofNullable(MacAppImageBuilder.
 277                     SIGN_BUNDLE.fetchFrom(p)).orElse(Boolean.FALSE)) {
 278             String signingIdentity = DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(p);
 279             if (signingIdentity == null) {
 280                 throw new ConfigException(
 281                         I18N.getString("error.explicit-sign-no-cert"),
 282                         I18N.getString("error.explicit-sign-no-cert.advice"));
 283             }
 284         }
 285 
 286         return true;
 287     }
 288 
 289     File doBundle(Map<String, ? super Object> p, File outputDirectory,
 290             boolean dependentTask) throws PackagerException {
 291         if (StandardBundlerParam.isRuntimeInstaller(p)) {
 292             return PREDEFINED_RUNTIME_IMAGE.fetchFrom(p);
 293         } else {
 294             return doAppBundle(p, outputDirectory, dependentTask);
 295         }
 296     }
 297 






















 298     File doAppBundle(Map<String, ? super Object> p, File outputDirectory,
 299             boolean dependentTask) throws PackagerException {
 300         try {
 301             File rootDirectory = createRoot(p, outputDirectory, dependentTask,
 302                     APP_NAME.fetchFrom(p) + ".app");
 303             AbstractAppImageBuilder appBuilder =
 304                     new MacAppImageBuilder(p, outputDirectory.toPath());
 305             if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) {
 306                 JLinkBundlerHelper.execute(p, appBuilder);
 307             } else {
 308                 StandardBundlerParam.copyPredefinedRuntimeImage(p, appBuilder);
 309             }
 310             return rootDirectory;
 311         } catch (PackagerException pe) {
 312             throw pe;
 313         } catch (Exception ex) {
 314             Log.verbose(ex);
 315             throw new PackagerException(ex);
 316         }
 317     }
 318 
 319     /////////////////////////////////////////////////////////////////////////
 320     // Implement Bundler
 321     /////////////////////////////////////////////////////////////////////////
 322 


< prev index next >