< prev index next >

src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java

Print this page




 351         // JDK 9, 10, and 11 have extra '/jli/' subdir
 352         Path jli = runtimeRoot.resolve("lib/libjli.dylib");
 353         if (!Files.exists(jli)) {
 354             jli = runtimeRoot.resolve("lib/jli/libjli.dylib");
 355         }
 356 
 357         Files.copy(jli, runtimeMacOSDir.resolve("libjli.dylib"));
 358     }
 359 
 360     private void sign(Map<String, ? super Object> params) throws IOException {
 361         if (Optional.ofNullable(
 362                 SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) {
 363             try {
 364                 addNewKeychain(params);
 365             } catch (InterruptedException e) {
 366                 Log.error(e.getMessage());
 367             }
 368             String signingIdentity =
 369                     DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
 370             if (signingIdentity != null) {

 371                 signAppBundle(params, root, signingIdentity,
 372                         BUNDLE_ID_SIGNING_PREFIX.fetchFrom(params), null, null);


 373             }
 374             restoreKeychainList(params);
 375         }
 376     }
 377 
























 378     private String getLauncherName(Map<String, ? super Object> params) {
 379         if (APP_NAME.fetchFrom(params) != null) {
 380             return APP_NAME.fetchFrom(params);
 381         } else {
 382             return MAIN_CLASS.fetchFrom(params);
 383         }
 384     }
 385 
 386     public static String getLauncherCfgName(
 387             Map<String, ? super Object> params) {
 388         return "Contents/app/" + APP_NAME.fetchFrom(params) + ".cfg";
 389     }
 390 
 391     private void copyClassPathEntries(Path javaDirectory,
 392             Map<String, ? super Object> params) throws IOException {
 393         List<RelativeFileSet> resourcesList =
 394                 APP_RESOURCES_LIST.fetchFrom(params);
 395         if (resourcesList == null) {
 396             throw new RuntimeException(
 397                     I18N.getString("message.null-classpath"));


 745         String keyChain = SIGNING_KEYCHAIN.fetchFrom(params);
 746 
 747         // sign all dylibs and jars
 748         try (Stream<Path> stream = Files.walk(appLocation)) {
 749             stream.peek(path -> { // fix permissions
 750                 try {
 751                     Set<PosixFilePermission> pfp =
 752                             Files.getPosixFilePermissions(path);
 753                     if (!pfp.contains(PosixFilePermission.OWNER_WRITE)) {
 754                         pfp = EnumSet.copyOf(pfp);
 755                         pfp.add(PosixFilePermission.OWNER_WRITE);
 756                         Files.setPosixFilePermissions(path, pfp);
 757                     }
 758                 } catch (IOException e) {
 759                     Log.verbose(e);
 760                 }
 761             }).filter(p -> Files.isRegularFile(p)
 762                       && !(p.toString().contains("/Contents/MacOS/libjli.dylib")
 763                       || p.toString().endsWith(appExecutable)
 764                       || p.toString().contains("/Contents/runtime")
 765                       || p.toString().contains("/Contents/Frameworks"))).forEach(p -> {

 766                 //noinspection ThrowableResultOfMethodCallIgnored
 767                 if (toThrow.get() != null) return;
 768 
 769                 // If p is a symlink then skip the signing process.
 770                 if (Files.isSymbolicLink(p)) {
 771                     if (VERBOSE.fetchFrom(params)) {
 772                         Log.verbose(MessageFormat.format(I18N.getString(
 773                                 "message.ignoring.symlink"), p.toString()));
 774                     }
 775                 } else {
 776                     if (p.toString().endsWith(LIBRARY_NAME)) {
 777                         if (isFileSigned(p)) {
 778                             return;
 779                         }
 780                     }
 781 
 782                     List<String> args = new ArrayList<>();
 783                     args.addAll(Arrays.asList("codesign",
 784                             "-s", signingIdentity, // sign with this key




 785                             "--prefix", identifierPrefix,
 786                             // use the identifier as a prefix
 787                             "-vvvv"));
 788                     if (entitlementsFile != null &&
 789                             (p.toString().endsWith(".jar")
 790                             || p.toString().endsWith(".dylib"))) {
 791                         args.add("--entitlements");
 792                         args.add(entitlementsFile); // entitlements
 793                     } else if (inheritedEntitlements != null &&
 794                             Files.isExecutable(p)) {
 795                         args.add("--entitlements");
 796                         args.add(inheritedEntitlements);
 797                         // inherited entitlements for executable processes
 798                     }
 799                     if (keyChain != null && !keyChain.isEmpty()) {
 800                         args.add("--keychain");
 801                         args.add(keyChain);
 802                     }
 803                     args.add(p.toString());
 804 
 805                     try {
 806                         Set<PosixFilePermission> oldPermissions =


 819             });
 820         }
 821         IOException ioe = toThrow.get();
 822         if (ioe != null) {
 823             throw ioe;
 824         }
 825 
 826         // sign all runtime and frameworks
 827         Consumer<? super Path> signIdentifiedByPList = path -> {
 828             //noinspection ThrowableResultOfMethodCallIgnored
 829             if (toThrow.get() != null) return;
 830 
 831             try {
 832                 List<String> args = new ArrayList<>();
 833                 args.addAll(Arrays.asList("codesign",
 834                         "-f",
 835                         "-s", signingIdentity, // sign with this key
 836                         "--prefix", identifierPrefix,
 837                         // use the identifier as a prefix
 838                         "-vvvv"));













 839                 if (keyChain != null && !keyChain.isEmpty()) {
 840                     args.add("--keychain");
 841                     args.add(keyChain);
 842                 }
 843                 args.add(path.toString());
 844                 ProcessBuilder pb = new ProcessBuilder(args);
 845                 IOUtils.exec(pb);
 846 

 847                 args = new ArrayList<>();
 848                 args.addAll(Arrays.asList("codesign",
 849                         "-s", signingIdentity, // sign with this key




 850                         "--prefix", identifierPrefix,
 851                         // use the identifier as a prefix
 852                         "-vvvv"));
 853                 if (keyChain != null && !keyChain.isEmpty()) {
 854                     args.add("--keychain");
 855                     args.add(keyChain);
 856                 }
 857                 args.add(path.toString()
 858                         + "/Contents/_CodeSignature/CodeResources");
 859                 pb = new ProcessBuilder(args);
 860                 IOUtils.exec(pb);
 861             } catch (IOException e) {
 862                 toThrow.set(e);
 863             }
 864         };
 865 
 866         Path javaPath = appLocation.resolve("Contents/runtime");
 867         if (Files.isDirectory(javaPath)) {
 868             signIdentifiedByPList.accept(javaPath);
 869 
 870             ioe = toThrow.get();
 871             if (ioe != null) {
 872                 throw ioe;
 873             }
 874         }
 875         Path frameworkPath = appLocation.resolve("Contents/Frameworks");
 876         if (Files.isDirectory(frameworkPath)) {
 877             Files.list(frameworkPath)
 878                     .forEach(signIdentifiedByPList);
 879 
 880             ioe = toThrow.get();
 881             if (ioe != null) {
 882                 throw ioe;
 883             }
 884         }
 885 
 886         // sign the app itself
 887         List<String> args = new ArrayList<>();
 888         args.addAll(Arrays.asList("codesign",
 889                 "-s", signingIdentity, // sign with this key
 890                 "-vvvv")); // super verbose output




 891         if (entitlementsFile != null) {
 892             args.add("--entitlements");
 893             args.add(entitlementsFile); // entitlements
 894         }
 895         if (keyChain != null && !keyChain.isEmpty()) {
 896             args.add("--keychain");
 897             args.add(keyChain);
 898         }
 899         args.add(appLocation.toString());
 900 
 901         ProcessBuilder pb =
 902                 new ProcessBuilder(args.toArray(new String[args.size()]));
 903         IOUtils.exec(pb);
 904     }
 905 
 906     private static boolean isFileSigned(Path file) {
 907         ProcessBuilder pb =
 908                 new ProcessBuilder("codesign", "--verify", file.toString());
 909 
 910         try {




 351         // JDK 9, 10, and 11 have extra '/jli/' subdir
 352         Path jli = runtimeRoot.resolve("lib/libjli.dylib");
 353         if (!Files.exists(jli)) {
 354             jli = runtimeRoot.resolve("lib/jli/libjli.dylib");
 355         }
 356 
 357         Files.copy(jli, runtimeMacOSDir.resolve("libjli.dylib"));
 358     }
 359 
 360     private void sign(Map<String, ? super Object> params) throws IOException {
 361         if (Optional.ofNullable(
 362                 SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) {
 363             try {
 364                 addNewKeychain(params);
 365             } catch (InterruptedException e) {
 366                 Log.error(e.getMessage());
 367             }
 368             String signingIdentity =
 369                     DEVELOPER_ID_APP_SIGNING_KEY.fetchFrom(params);
 370             if (signingIdentity != null) {
 371                 prepareEntitlements(params);
 372                 signAppBundle(params, root, signingIdentity,
 373                         BUNDLE_ID_SIGNING_PREFIX.fetchFrom(params),
 374                         getConfig_Entitlements(params).toString(),
 375                         getConfig_Inherit_Entitlements(params).toString());
 376             }
 377             restoreKeychainList(params);
 378         }
 379     }
 380 
 381     private File getConfig_Entitlements(Map<String, ? super Object> params) {
 382         return new File(CONFIG_ROOT.fetchFrom(params),
 383                 getLauncherName(params) + ".entitlements");
 384     }
 385 
 386     private File getConfig_Inherit_Entitlements(
 387             Map<String, ? super Object> params) {
 388         return new File(CONFIG_ROOT.fetchFrom(params), 
 389                 getLauncherName(params) + "_Inherit.entitlements");
 390     }
 391 
 392     private void prepareEntitlements(Map<String, ? super Object> params)
 393             throws IOException {
 394         createResource("Mac.entitlements", params)
 395                 .setCategory(I18N.getString("resource.mac-entitlements"))
 396                 .saveToFile(getConfig_Entitlements(params));
 397 
 398         createResource("Mac_Inherit.entitlements", params)
 399                 .setCategory(I18N.getString(
 400                         "resource.mac-inherit-entitlements"))
 401                 .saveToFile(getConfig_Inherit_Entitlements(params));
 402     }
 403 
 404 
 405     private String getLauncherName(Map<String, ? super Object> params) {
 406         if (APP_NAME.fetchFrom(params) != null) {
 407             return APP_NAME.fetchFrom(params);
 408         } else {
 409             return MAIN_CLASS.fetchFrom(params);
 410         }
 411     }
 412 
 413     public static String getLauncherCfgName(
 414             Map<String, ? super Object> params) {
 415         return "Contents/app/" + APP_NAME.fetchFrom(params) + ".cfg";
 416     }
 417 
 418     private void copyClassPathEntries(Path javaDirectory,
 419             Map<String, ? super Object> params) throws IOException {
 420         List<RelativeFileSet> resourcesList =
 421                 APP_RESOURCES_LIST.fetchFrom(params);
 422         if (resourcesList == null) {
 423             throw new RuntimeException(
 424                     I18N.getString("message.null-classpath"));


 772         String keyChain = SIGNING_KEYCHAIN.fetchFrom(params);
 773 
 774         // sign all dylibs and jars
 775         try (Stream<Path> stream = Files.walk(appLocation)) {
 776             stream.peek(path -> { // fix permissions
 777                 try {
 778                     Set<PosixFilePermission> pfp =
 779                             Files.getPosixFilePermissions(path);
 780                     if (!pfp.contains(PosixFilePermission.OWNER_WRITE)) {
 781                         pfp = EnumSet.copyOf(pfp);
 782                         pfp.add(PosixFilePermission.OWNER_WRITE);
 783                         Files.setPosixFilePermissions(path, pfp);
 784                     }
 785                 } catch (IOException e) {
 786                     Log.verbose(e);
 787                 }
 788             }).filter(p -> Files.isRegularFile(p)
 789                       && !(p.toString().contains("/Contents/MacOS/libjli.dylib")
 790                       || p.toString().endsWith(appExecutable)
 791                       || p.toString().contains("/Contents/runtime")
 792                       || p.toString().contains("/Contents/Frameworks"))
 793                      ).forEach(p -> {
 794                 //noinspection ThrowableResultOfMethodCallIgnored
 795                 if (toThrow.get() != null) return;
 796 
 797                 // If p is a symlink then skip the signing process.
 798                 if (Files.isSymbolicLink(p)) {
 799                     if (VERBOSE.fetchFrom(params)) {
 800                         Log.verbose(MessageFormat.format(I18N.getString(
 801                                 "message.ignoring.symlink"), p.toString()));
 802                     }
 803                 } else {
 804                     if (p.toString().endsWith(LIBRARY_NAME)) {
 805                         if (isFileSigned(p)) {
 806                             return;
 807                         }
 808                     }

 809                     List<String> args = new ArrayList<>();
 810                     args.addAll(Arrays.asList("codesign",
 811                             "--timestamp",
 812                             "--options", "runtime",
 813                             "--deep",
 814                             "--force",
 815                             "-s", signingIdentity,
 816                             "--prefix", identifierPrefix,

 817                             "-vvvv"));
 818                     if (entitlementsFile != null &&
 819                             (p.toString().endsWith(".jar")
 820                             || p.toString().endsWith(".dylib"))) {
 821                         args.add("--entitlements");
 822                         args.add(entitlementsFile); // entitlements
 823                     } else if (inheritedEntitlements != null &&
 824                             Files.isExecutable(p)) {
 825                         args.add("--entitlements");
 826                         args.add(inheritedEntitlements);
 827                         // inherited entitlements for executable processes
 828                     }
 829                     if (keyChain != null && !keyChain.isEmpty()) {
 830                         args.add("--keychain");
 831                         args.add(keyChain);
 832                     }
 833                     args.add(p.toString());
 834 
 835                     try {
 836                         Set<PosixFilePermission> oldPermissions =


 849             });
 850         }
 851         IOException ioe = toThrow.get();
 852         if (ioe != null) {
 853             throw ioe;
 854         }
 855 
 856         // sign all runtime and frameworks
 857         Consumer<? super Path> signIdentifiedByPList = path -> {
 858             //noinspection ThrowableResultOfMethodCallIgnored
 859             if (toThrow.get() != null) return;
 860 
 861             try {
 862                 List<String> args = new ArrayList<>();
 863                 args.addAll(Arrays.asList("codesign",
 864                         "-f",
 865                         "-s", signingIdentity, // sign with this key
 866                         "--prefix", identifierPrefix,
 867                         // use the identifier as a prefix
 868                         "-vvvv"));
 869 
 870                 if (entitlementsFile != null &&
 871                         (path.toString().endsWith(".jar")
 872                         || path.toString().endsWith(".dylib"))) {
 873                     args.add("--entitlements");
 874                     args.add(entitlementsFile); // entitlements
 875                 } else if (inheritedEntitlements != null &&
 876                         Files.isExecutable(path)) {
 877                     args.add("--entitlements");
 878                     args.add(inheritedEntitlements);
 879                     // inherited entitlements for executable processes
 880                 }
 881 
 882                 if (keyChain != null && !keyChain.isEmpty()) {
 883                     args.add("--keychain");
 884                     args.add(keyChain);
 885                 }
 886                 args.add(path.toString());
 887                 ProcessBuilder pb = new ProcessBuilder(args);
 888                 IOUtils.exec(pb);
 889 
 890 
 891                 args = new ArrayList<>();
 892                 args.addAll(Arrays.asList("codesign",
 893                         "--timestamp",
 894                         "--options", "runtime",
 895                         "--deep",
 896                         "--force",
 897                         "-s", signingIdentity,
 898                         "--prefix", identifierPrefix,

 899                         "-vvvv"));
 900                 if (keyChain != null && !keyChain.isEmpty()) {
 901                     args.add("--keychain");
 902                     args.add(keyChain);
 903                 }
 904                 args.add(path.toString()
 905                         + "/Contents/_CodeSignature/CodeResources");
 906                 pb = new ProcessBuilder(args);
 907                 IOUtils.exec(pb);
 908             } catch (IOException e) {
 909                 toThrow.set(e);
 910             }
 911         };
 912 
 913         Path javaPath = appLocation.resolve("Contents/runtime");
 914         if (Files.isDirectory(javaPath)) {
 915             signIdentifiedByPList.accept(javaPath);
 916 
 917             ioe = toThrow.get();
 918             if (ioe != null) {
 919                 throw ioe;
 920             }
 921         }
 922         Path frameworkPath = appLocation.resolve("Contents/Frameworks");
 923         if (Files.isDirectory(frameworkPath)) {
 924             Files.list(frameworkPath)
 925                     .forEach(signIdentifiedByPList);
 926 
 927             ioe = toThrow.get();
 928             if (ioe != null) {
 929                 throw ioe;
 930             }
 931         }
 932 
 933         // sign the app itself
 934         List<String> args = new ArrayList<>();
 935         args.addAll(Arrays.asList("codesign",
 936                 "--timestamp",
 937                 "--options", "runtime",
 938                 "--deep",
 939                 "--force",
 940                 "-s", signingIdentity,
 941                 "-vvvv"));
 942         if (entitlementsFile != null) {
 943             args.add("--entitlements");
 944             args.add(entitlementsFile); // entitlements
 945         }
 946         if (keyChain != null && !keyChain.isEmpty()) {
 947             args.add("--keychain");
 948             args.add(keyChain);
 949         }
 950         args.add(appLocation.toString());
 951 
 952         ProcessBuilder pb =
 953                 new ProcessBuilder(args.toArray(new String[args.size()]));
 954         IOUtils.exec(pb);
 955     }
 956 
 957     private static boolean isFileSigned(Path file) {
 958         ProcessBuilder pb =
 959                 new ProcessBuilder("codesign", "--verify", file.toString());
 960 
 961         try {


< prev index next >