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 | 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 -> params.containsKey(CATEGORY.getID()) 103 ? CATEGORY.fetchFrom(params) 104 : "Unknown", 105 (s, p) -> s, 106 getMacCategories(), 107 false //strict - for MacStoreBundler this should be strict 108 ); 109 110 public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME = 111 new StandardBundlerParam<>( 112 Arguments.CLIOptions.MAC_BUNDLE_NAME.getId(), 113 String.class, 114 params -> null, 115 (s, p) -> s); 116 117 public static final BundlerParamInfo<String> MAC_CF_BUNDLE_IDENTIFIER = 118 new StandardBundlerParam<>( 119 Arguments.CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(), 120 String.class, 121 IDENTIFIER::fetchFrom, 122 (s, p) -> s); 123 124 public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION = 125 new StandardBundlerParam<>( 126 "mac.CFBundleVersion", 127 String.class, 128 p -> { 129 String s = VERSION.fetchFrom(p); 130 if (validCFBundleVersion(s)) { 131 return s; 132 } else { 133 return "100"; 134 } 135 }, 136 (s, p) -> s); 137 138 public static final BundlerParamInfo<String> DEFAULT_ICNS_ICON = 139 new StandardBundlerParam<>( 140 ".mac.default.icns", 141 String.class, 142 params -> TEMPLATE_BUNDLE_ICON, 143 (s, p) -> s); 144 145 public static final BundlerParamInfo<String> DEVELOPER_ID_APP_SIGNING_KEY = 146 new StandardBundlerParam<>( 147 "mac.signing-key-developer-id-app", 148 String.class, 149 params -> { 150 String result = MacBaseInstallerBundler.findKey( 151 "Developer ID Application: " 152 + SIGNING_KEY_USER.fetchFrom(params), 153 SIGNING_KEYCHAIN.fetchFrom(params), 154 VERBOSE.fetchFrom(params)); 155 if (result != null) { 156 MacCertificate certificate = new MacCertificate(result, 157 VERBOSE.fetchFrom(params)); 158 159 if (!certificate.isValid()) { 160 Log.error(MessageFormat.format(I18N.getString( 161 "error.certificate.expired"), result)); 162 } 163 } 164 165 return result; 166 }, 167 (s, p) -> s); 168 169 public static final BundlerParamInfo<String> BUNDLE_ID_SIGNING_PREFIX = 170 new StandardBundlerParam<>( 171 Arguments.CLIOptions.MAC_BUNDLE_SIGNING_PREFIX.getId(), 172 String.class, 173 params -> IDENTIFIER.fetchFrom(params) + ".", 174 (s, p) -> s); 175 176 public static final BundlerParamInfo<File> ICON_ICNS = 177 new StandardBundlerParam<>( 178 "icon.icns", 179 File.class, 180 params -> { 181 File f = ICON.fetchFrom(params); 182 if (f != null && !f.getName().toLowerCase().endsWith(".icns")) { 183 Log.error(MessageFormat.format( 184 I18N.getString("message.icon-not-icns"), f)); 185 return null; 186 } 187 return f; 188 }, 189 (s, p) -> new File(s)); 190 191 public static boolean validCFBundleVersion(String v) { 192 // CFBundleVersion (String - iOS, OS X) specifies the build version 193 // number of the bundle, which identifies an iteration (released or 194 // unreleased) of the bundle. The build version number should be a 195 // string comprised of three non-negative, period-separated integers 196 // with the first integer being greater than zero. The string should 197 // only contain numeric (0-9) and period (.) characters. Leading zeros 273 I18N.getString("error.invalid-cfbundle-version"), 274 I18N.getString("error.invalid-cfbundle-version.advice")); 275 } 276 277 // reject explicitly set sign to true and no valid signature key 278 if (Optional.ofNullable(MacAppImageBuilder. 279 SIGN_BUNDLE.fetchFrom(p)).orElse(Boolean.FALSE)) { 280 String signingIdentity = DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(p); 281 if (signingIdentity == null) { 282 throw new ConfigException( 283 I18N.getString("error.explicit-sign-no-cert"), 284 I18N.getString("error.explicit-sign-no-cert.advice")); 285 } 286 } 287 288 return true; 289 } 290 291 File doBundle(Map<String, ? super Object> p, File outputDirectory, 292 boolean dependentTask) throws PackagerException { 293 if (StandardBundlerParam.isRuntimeInstaller(p)) { 294 return PREDEFINED_RUNTIME_IMAGE.fetchFrom(p); 295 } else { 296 return doAppBundle(p, outputDirectory, dependentTask); 297 } 298 } 299 300 File doAppBundle(Map<String, ? super Object> p, File outputDirectory, 301 boolean dependentTask) throws PackagerException { 302 try { 303 File rootDirectory = createRoot(p, outputDirectory, dependentTask, 304 APP_NAME.fetchFrom(p) + ".app"); 305 AbstractAppImageBuilder appBuilder = 306 new MacAppImageBuilder(p, outputDirectory.toPath()); 307 if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) { 308 JLinkBundlerHelper.execute(p, appBuilder); 309 } else { 310 StandardBundlerParam.copyPredefinedRuntimeImage(p, appBuilder); 311 } 312 return rootDirectory; 313 } catch (PackagerException pe) { 314 throw pe; 315 } catch (Exception ex) { 316 Log.verbose(ex); 317 throw new PackagerException(ex); 318 } 319 } 320 321 ///////////////////////////////////////////////////////////////////////// 322 // Implement Bundler 323 ///////////////////////////////////////////////////////////////////////// 324 |