< prev index next >

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

Print this page

        

*** 21,42 **** * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! package jdk.jpackage.internal; - import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; - import java.io.FileOutputStream; - import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; - import java.io.OutputStream; - import java.io.OutputStreamWriter; - import java.io.UncheckedIOException; import java.io.Writer; import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; --- 21,36 ---- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ ! package jdk.incubator.jpackage.internal; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption;
*** 52,122 **** import java.util.Optional; import java.util.ResourceBundle; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; ! ! import static jdk.jpackage.internal.StandardBundlerParam.*; ! import static jdk.jpackage.internal.MacBaseInstallerBundler.*; ! import static jdk.jpackage.internal.MacAppBundler.*; public class MacAppImageBuilder extends AbstractAppImageBuilder { private static final ResourceBundle I18N = ResourceBundle.getBundle( ! "jdk.jpackage.internal.resources.MacResources"); private static final String LIBRARY_NAME = "libapplauncher.dylib"; ! private static final String TEMPLATE_BUNDLE_ICON = "GenericApp.icns"; private static final String OS_TYPE_CODE = "APPL"; private static final String TEMPLATE_INFO_PLIST_LITE = "Info-lite.plist.template"; private static final String TEMPLATE_RUNTIME_INFO_PLIST = "Runtime-Info.plist.template"; private final Path root; private final Path contentsDir; ! private final Path javaDir; private final Path javaModsDir; private final Path resourcesDir; private final Path macOSDir; private final Path runtimeDir; private final Path runtimeRoot; private final Path mdir; - private final Map<String, ? super Object> params; - private static List<String> keyChains; public static final BundlerParamInfo<Boolean> MAC_CONFIGURE_LAUNCHER_IN_PLIST = new StandardBundlerParam<>( "mac.configure-launcher-in-plist", Boolean.class, params -> Boolean.FALSE, (s, p) -> Boolean.valueOf(s)); - public static final EnumeratedBundlerParam<String> MAC_CATEGORY = - new EnumeratedBundlerParam<>( - Arguments.CLIOptions.MAC_APP_STORE_CATEGORY.getId(), - String.class, - params -> "Unknown", - (s, p) -> s, - MacAppBundler.getMacCategories(), - false //strict - for MacStoreBundler this should be strict - ); - public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME = new StandardBundlerParam<>( ! "mac.CFBundleName", String.class, params -> null, (s, p) -> s); public static final BundlerParamInfo<String> MAC_CF_BUNDLE_IDENTIFIER = new StandardBundlerParam<>( Arguments.CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(), String.class, ! IDENTIFIER::fetchFrom, (s, p) -> s); public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION = new StandardBundlerParam<>( "mac.CFBundleVersion", --- 46,120 ---- import java.util.Optional; import java.util.ResourceBundle; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; ! import java.util.stream.Stream; ! import javax.xml.parsers.DocumentBuilder; ! import javax.xml.parsers.DocumentBuilderFactory; ! import javax.xml.xpath.XPath; ! import javax.xml.xpath.XPathConstants; ! import javax.xml.xpath.XPathFactory; ! ! import static jdk.incubator.jpackage.internal.StandardBundlerParam.*; ! import static jdk.incubator.jpackage.internal.MacBaseInstallerBundler.*; ! import static jdk.incubator.jpackage.internal.MacAppBundler.*; ! import static jdk.incubator.jpackage.internal.OverridableResource.createResource; public class MacAppImageBuilder extends AbstractAppImageBuilder { private static final ResourceBundle I18N = ResourceBundle.getBundle( ! "jdk.incubator.jpackage.internal.resources.MacResources"); private static final String LIBRARY_NAME = "libapplauncher.dylib"; ! private static final String TEMPLATE_BUNDLE_ICON = "java.icns"; private static final String OS_TYPE_CODE = "APPL"; private static final String TEMPLATE_INFO_PLIST_LITE = "Info-lite.plist.template"; private static final String TEMPLATE_RUNTIME_INFO_PLIST = "Runtime-Info.plist.template"; private final Path root; private final Path contentsDir; ! private final Path appDir; private final Path javaModsDir; private final Path resourcesDir; private final Path macOSDir; private final Path runtimeDir; private final Path runtimeRoot; private final Path mdir; private static List<String> keyChains; public static final BundlerParamInfo<Boolean> MAC_CONFIGURE_LAUNCHER_IN_PLIST = new StandardBundlerParam<>( "mac.configure-launcher-in-plist", Boolean.class, params -> Boolean.FALSE, (s, p) -> Boolean.valueOf(s)); public static final BundlerParamInfo<String> MAC_CF_BUNDLE_NAME = new StandardBundlerParam<>( ! Arguments.CLIOptions.MAC_BUNDLE_NAME.getId(), String.class, params -> null, (s, p) -> s); public static final BundlerParamInfo<String> MAC_CF_BUNDLE_IDENTIFIER = new StandardBundlerParam<>( Arguments.CLIOptions.MAC_BUNDLE_IDENTIFIER.getId(), String.class, ! params -> { ! // Get identifier from app image if user provided ! // app image and did not provide the identifier via CLI. ! String identifier = extractBundleIdentifier(params); ! if (identifier != null) { ! return identifier; ! } ! ! return IDENTIFIER.fetchFrom(params); ! }, (s, p) -> s); public static final BundlerParamInfo<String> MAC_CF_BUNDLE_VERSION = new StandardBundlerParam<>( "mac.CFBundleVersion",
*** 129,145 **** return "100"; } }, (s, p) -> s); - public static final BundlerParamInfo<String> DEFAULT_ICNS_ICON = - new StandardBundlerParam<>( - ".mac.default.icns", - String.class, - params -> TEMPLATE_BUNDLE_ICON, - (s, p) -> s); - public static final BundlerParamInfo<File> ICON_ICNS = new StandardBundlerParam<>( "icon.icns", File.class, params -> { --- 127,136 ----
*** 161,240 **** // valueOf(null) is false, we actually do want null in some cases (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ? null : Boolean.valueOf(s) ); ! public MacAppImageBuilder(Map<String, Object> config, Path imageOutDir) throws IOException { ! super(config, imageOutDir.resolve(APP_NAME.fetchFrom(config) + ".app/Contents/runtime/Contents/Home")); Objects.requireNonNull(imageOutDir); - this.params = config; this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params) + ".app"); this.contentsDir = root.resolve("Contents"); ! this.javaDir = contentsDir.resolve("Java"); ! this.javaModsDir = javaDir.resolve("mods"); this.resourcesDir = contentsDir.resolve("Resources"); this.macOSDir = contentsDir.resolve("MacOS"); this.runtimeDir = contentsDir.resolve("runtime"); this.runtimeRoot = runtimeDir.resolve("Contents/Home"); this.mdir = runtimeRoot.resolve("lib"); ! Files.createDirectories(javaDir); Files.createDirectories(resourcesDir); Files.createDirectories(macOSDir); Files.createDirectories(runtimeDir); } - public MacAppImageBuilder(Map<String, Object> config, String jreName, - Path imageOutDir) throws IOException { - super(null, imageOutDir.resolve(jreName + "/Contents/Home")); - - Objects.requireNonNull(imageOutDir); - - this.params = config; - this.root = imageOutDir.resolve(jreName ); - this.contentsDir = root.resolve("Contents"); - this.javaDir = null; - this.javaModsDir = null; - this.resourcesDir = null; - this.macOSDir = null; - this.runtimeDir = this.root; - this.runtimeRoot = runtimeDir.resolve("Contents/Home"); - this.mdir = runtimeRoot.resolve("lib"); - - Files.createDirectories(runtimeDir); - } - private void writeEntry(InputStream in, Path dstFile) throws IOException { Files.createDirectories(dstFile.getParent()); Files.copy(in, dstFile); } - // chmod ugo+x file - private void setExecutable(Path file) { - try { - Set<PosixFilePermission> perms = - Files.getPosixFilePermissions(file); - perms.add(PosixFilePermission.OWNER_EXECUTE); - perms.add(PosixFilePermission.GROUP_EXECUTE); - perms.add(PosixFilePermission.OTHERS_EXECUTE); - Files.setPosixFilePermissions(file, perms); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - } - - private static void createUtf8File(File file, String content) - throws IOException { - try (OutputStream fout = new FileOutputStream(file); - Writer output = new OutputStreamWriter(fout, "UTF-8")) { - output.write(content); - } - } - public static boolean validCFBundleVersion(String v) { // CFBundleVersion (String - iOS, OS X) specifies the build version // number of the bundle, which identifies an iteration (released or // unreleased) of the bundle. The build version number should be a // string comprised of three non-negative, period-separated integers --- 152,188 ---- // valueOf(null) is false, we actually do want null in some cases (s, p) -> (s == null || "null".equalsIgnoreCase(s)) ? null : Boolean.valueOf(s) ); ! public MacAppImageBuilder(Map<String, Object> params, Path imageOutDir) throws IOException { ! super(params, imageOutDir.resolve(APP_NAME.fetchFrom(params) + ".app/Contents/runtime/Contents/Home")); Objects.requireNonNull(imageOutDir); this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params) + ".app"); this.contentsDir = root.resolve("Contents"); ! this.appDir = contentsDir.resolve("app"); ! this.javaModsDir = appDir.resolve("mods"); this.resourcesDir = contentsDir.resolve("Resources"); this.macOSDir = contentsDir.resolve("MacOS"); this.runtimeDir = contentsDir.resolve("runtime"); this.runtimeRoot = runtimeDir.resolve("Contents/Home"); this.mdir = runtimeRoot.resolve("lib"); ! Files.createDirectories(appDir); Files.createDirectories(resourcesDir); Files.createDirectories(macOSDir); Files.createDirectories(runtimeDir); } private void writeEntry(InputStream in, Path dstFile) throws IOException { Files.createDirectories(dstFile.getParent()); Files.copy(in, dstFile); } public static boolean validCFBundleVersion(String v) { // CFBundleVersion (String - iOS, OS X) specifies the build version // number of the bundle, which identifies an iteration (released or // unreleased) of the bundle. The build version number should be a // string comprised of three non-negative, period-separated integers
*** 286,305 **** return true; } @Override public Path getAppDir() { ! return javaDir; } @Override public Path getAppModsDir() { return javaModsDir; } @Override ! public void prepareApplicationFiles() throws IOException { Map<String, ? super Object> originalParams = new HashMap<>(params); // Generate PkgInfo File pkgInfoFile = new File(contentsDir.toFile(), "PkgInfo"); pkgInfoFile.createNewFile(); writePkgInfo(pkgInfoFile); --- 234,254 ---- return true; } @Override public Path getAppDir() { ! return appDir; } @Override public Path getAppModsDir() { return javaModsDir; } @Override ! public void prepareApplicationFiles(Map<String, ? super Object> params) ! throws IOException { Map<String, ? super Object> originalParams = new HashMap<>(params); // Generate PkgInfo File pkgInfoFile = new File(contentsDir.toFile(), "PkgInfo"); pkgInfoFile.createNewFile(); writePkgInfo(pkgInfoFile);
*** 315,325 **** writeEntry(is_lib, macOSDir.resolve(LIBRARY_NAME)); } executable.toFile().setExecutable(true, false); // generate main app launcher config file File cfg = new File(root.toFile(), getLauncherCfgName(params)); ! writeCfgFile(params, cfg, "$APPDIR/runtime"); // create additional app launcher(s) and config file(s) List<Map<String, ? super Object>> entryPoints = StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params); for (Map<String, ? super Object> entryPoint : entryPoints) { --- 264,274 ---- writeEntry(is_lib, macOSDir.resolve(LIBRARY_NAME)); } executable.toFile().setExecutable(true, false); // generate main app launcher config file File cfg = new File(root.toFile(), getLauncherCfgName(params)); ! writeCfgFile(params, cfg); // create additional app launcher(s) and config file(s) List<Map<String, ? super Object>> entryPoints = StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params); for (Map<String, ? super Object> entryPoint : entryPoints) {
*** 333,361 **** } addExecutable.toFile().setExecutable(true, false); // add config file for add launcher cfg = new File(root.toFile(), getLauncherCfgName(tmp)); ! writeCfgFile(tmp, cfg, "$APPDIR/runtime"); } // Copy class path entries to Java folder ! copyClassPathEntries(javaDir); /*********** Take care of "config" files *******/ - File icon = ICON_ICNS.fetchFrom(params); ! InputStream in = locateResource( ! APP_NAME.fetchFrom(params) + ".icns", ! "icon", ! DEFAULT_ICNS_ICON.fetchFrom(params), ! icon, ! VERBOSE.fetchFrom(params), ! RESOURCE_DIR.fetchFrom(params)); ! Files.copy(in, ! resourcesDir.resolve(APP_NAME.fetchFrom(params) + ".icns"), ! StandardCopyOption.REPLACE_EXISTING); // copy file association icons for (Map<String, ? super Object> fa : FILE_ASSOCIATIONS.fetchFrom(params)) { File f = FA_ICON.fetchFrom(fa); --- 282,304 ---- } addExecutable.toFile().setExecutable(true, false); // add config file for add launcher cfg = new File(root.toFile(), getLauncherCfgName(tmp)); ! writeCfgFile(tmp, cfg); } // Copy class path entries to Java folder ! copyClassPathEntries(appDir, params); /*********** Take care of "config" files *******/ ! createResource(TEMPLATE_BUNDLE_ICON, params) ! .setCategory("icon") ! .setExternal(ICON_ICNS.fetchFrom(params)) ! .saveToFile(resourcesDir.resolve(APP_NAME.fetchFrom(params) ! + ".icns")); // copy file association icons for (Map<String, ? super Object> fa : FILE_ASSOCIATIONS.fetchFrom(params)) { File f = FA_ICON.fetchFrom(fa);
*** 365,391 **** } } } ! copyRuntimeFiles(); ! sign(); } @Override ! public void prepareJreFiles() throws IOException { ! copyRuntimeFiles(); ! sign(); } ! private void copyRuntimeFiles() throws IOException { // Generate Info.plist ! writeInfoPlist(contentsDir.resolve("Info.plist").toFile()); // generate java runtime info.plist writeRuntimeInfoPlist( ! runtimeDir.resolve("Contents/Info.plist").toFile()); // copy library Path runtimeMacOSDir = Files.createDirectories( runtimeDir.resolve("Contents/MacOS")); --- 308,342 ---- } } } ! copyRuntimeFiles(params); ! sign(params); } @Override ! public void prepareJreFiles(Map<String, ? super Object> params) ! throws IOException { ! copyRuntimeFiles(params); ! sign(params); } ! @Override ! File getRuntimeImageDir(File runtimeImageTop) { ! File home = new File(runtimeImageTop, "Contents/Home"); ! return (home.exists() ? home : runtimeImageTop); ! } ! ! private void copyRuntimeFiles(Map<String, ? super Object> params) ! throws IOException { // Generate Info.plist ! writeInfoPlist(contentsDir.resolve("Info.plist").toFile(), params); // generate java runtime info.plist writeRuntimeInfoPlist( ! runtimeDir.resolve("Contents/Info.plist").toFile(), params); // copy library Path runtimeMacOSDir = Files.createDirectories( runtimeDir.resolve("Contents/MacOS"));
*** 396,406 **** } Files.copy(jli, runtimeMacOSDir.resolve("libjli.dylib")); } ! private void sign() throws IOException { if (Optional.ofNullable( SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) { try { addNewKeychain(params); } catch (InterruptedException e) { --- 347,357 ---- } Files.copy(jli, runtimeMacOSDir.resolve("libjli.dylib")); } ! private void sign(Map<String, ? super Object> params) throws IOException { if (Optional.ofNullable( SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) { try { addNewKeychain(params); } catch (InterruptedException e) {
*** 422,436 **** } else { return MAIN_CLASS.fetchFrom(params); } } ! public static String getLauncherCfgName(Map<String, ? super Object> p) { ! return "Contents/Java/" + APP_NAME.fetchFrom(p) + ".cfg"; } ! private void copyClassPathEntries(Path javaDirectory) throws IOException { List<RelativeFileSet> resourcesList = APP_RESOURCES_LIST.fetchFrom(params); if (resourcesList == null) { throw new RuntimeException( I18N.getString("message.null-classpath")); --- 373,389 ---- } else { return MAIN_CLASS.fetchFrom(params); } } ! public static String getLauncherCfgName( ! Map<String, ? super Object> params) { ! return "Contents/app/" + APP_NAME.fetchFrom(params) + ".cfg"; } ! private void copyClassPathEntries(Path javaDirectory, ! Map<String, ? super Object> params) throws IOException { List<RelativeFileSet> resourcesList = APP_RESOURCES_LIST.fetchFrom(params); if (resourcesList == null) { throw new RuntimeException( I18N.getString("message.null-classpath"));
*** 462,472 **** } return nm; } } ! private void writeRuntimeInfoPlist(File file) throws IOException { Map<String, String> data = new HashMap<>(); String identifier = StandardBundlerParam.isRuntimeInstaller(params) ? MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) : "com.oracle.java." + MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params); data.put("CF_BUNDLE_IDENTIFIER", identifier); --- 415,426 ---- } return nm; } } ! private void writeRuntimeInfoPlist(File file, ! Map<String, ? super Object> params) throws IOException { Map<String, String> data = new HashMap<>(); String identifier = StandardBundlerParam.isRuntimeInstaller(params) ? MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) : "com.oracle.java." + MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params); data.put("CF_BUNDLE_IDENTIFIER", identifier);
*** 474,494 **** getBundleName(params): "Java Runtime Image"; data.put("CF_BUNDLE_NAME", name); data.put("CF_BUNDLE_VERSION", VERSION.fetchFrom(params)); data.put("CF_BUNDLE_SHORT_VERSION_STRING", VERSION.fetchFrom(params)); ! Writer w = new BufferedWriter(new FileWriter(file)); ! w.write(preprocessTextResource("Runtime-Info.plist", ! I18N.getString("resource.runtime-info-plist"), ! TEMPLATE_RUNTIME_INFO_PLIST, ! data, ! VERBOSE.fetchFrom(params), ! RESOURCE_DIR.fetchFrom(params))); ! w.close(); } ! private void writeInfoPlist(File file) throws IOException { Log.verbose(MessageFormat.format(I18N.getString( "message.preparing-info-plist"), file.getAbsolutePath())); //prepare config for exe //Note: do not need CFBundleDisplayName if we don't support localization --- 428,446 ---- getBundleName(params): "Java Runtime Image"; data.put("CF_BUNDLE_NAME", name); data.put("CF_BUNDLE_VERSION", VERSION.fetchFrom(params)); data.put("CF_BUNDLE_SHORT_VERSION_STRING", VERSION.fetchFrom(params)); ! createResource(TEMPLATE_RUNTIME_INFO_PLIST, params) ! .setPublicName("Runtime-Info.plist") ! .setCategory(I18N.getString("resource.runtime-info-plist")) ! .setSubstitutionData(data) ! .saveToFile(file); } ! private void writeInfoPlist(File file, Map<String, ? super Object> params) ! throws IOException { Log.verbose(MessageFormat.format(I18N.getString( "message.preparing-info-plist"), file.getAbsolutePath())); //prepare config for exe //Note: do not need CFBundleDisplayName if we don't support localization
*** 500,517 **** getBundleName(params)); data.put("DEPLOY_BUNDLE_COPYRIGHT", COPYRIGHT.fetchFrom(params) != null ? COPYRIGHT.fetchFrom(params) : "Unknown"); data.put("DEPLOY_LAUNCHER_NAME", getLauncherName(params)); - data.put("DEPLOY_JAVA_RUNTIME_NAME", "$APPDIR/runtime"); data.put("DEPLOY_BUNDLE_SHORT_VERSION", VERSION.fetchFrom(params) != null ? VERSION.fetchFrom(params) : "1.0.0"); data.put("DEPLOY_BUNDLE_CFBUNDLE_VERSION", MAC_CF_BUNDLE_VERSION.fetchFrom(params) != null ? MAC_CF_BUNDLE_VERSION.fetchFrom(params) : "100"); - data.put("DEPLOY_BUNDLE_CATEGORY", MAC_CATEGORY.fetchFrom(params)); boolean hasMainJar = MAIN_JAR.fetchFrom(params) != null; boolean hasMainModule = StandardBundlerParam.MODULE.fetchFrom(params) != null; --- 452,467 ----
*** 550,567 **** newline = ""; data.put("DEPLOY_LAUNCHER_CLASS", MAIN_CLASS.fetchFrom(params)); ! StringBuilder macroedPath = new StringBuilder(); ! for (String s : CLASSPATH.fetchFrom(params).split("[ ;:]+")) { ! macroedPath.append(s); ! macroedPath.append(":"); ! } ! macroedPath.deleteCharAt(macroedPath.length() - 1); ! ! data.put("DEPLOY_APP_CLASSPATH", macroedPath.toString()); StringBuilder bundleDocumentTypes = new StringBuilder(); StringBuilder exportedTypes = new StringBuilder(); for (Map<String, ? super Object> fileAssociation : FILE_ASSOCIATIONS.fetchFrom(params)) { --- 500,511 ---- newline = ""; data.put("DEPLOY_LAUNCHER_CLASS", MAIN_CLASS.fetchFrom(params)); ! data.put("DEPLOY_APP_CLASSPATH", ! getCfgClassPath(CLASSPATH.fetchFrom(params))); StringBuilder bundleDocumentTypes = new StringBuilder(); StringBuilder exportedTypes = new StringBuilder(); for (Map<String, ? super Object> fileAssociation : FILE_ASSOCIATIONS.fetchFrom(params)) {
*** 576,586 **** List<String> mimeTypes = FA_CONTENT_TYPE.fetchFrom(fileAssociation); String itemContentType = MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) + "." + ((extensions == null || extensions.isEmpty()) ? "mime" : extensions.get(0)); String description = FA_DESCRIPTION.fetchFrom(fileAssociation); ! File icon = FA_ICON.fetchFrom(fileAssociation); //TODO FA_ICON_ICNS bundleDocumentTypes.append(" <dict>\n") .append(" <key>LSItemContentTypes</key>\n") .append(" <array>\n") .append(" <string>") --- 520,530 ---- List<String> mimeTypes = FA_CONTENT_TYPE.fetchFrom(fileAssociation); String itemContentType = MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) + "." + ((extensions == null || extensions.isEmpty()) ? "mime" : extensions.get(0)); String description = FA_DESCRIPTION.fetchFrom(fileAssociation); ! File icon = FA_ICON.fetchFrom(fileAssociation); bundleDocumentTypes.append(" <dict>\n") .append(" <key>LSItemContentTypes</key>\n") .append(" <array>\n") .append(" <string>")
*** 687,713 **** } else { associationData = ""; } data.put("DEPLOY_FILE_ASSOCIATIONS", associationData); ! ! Writer w = new BufferedWriter(new FileWriter(file)); ! w.write(preprocessTextResource( ! // getConfig_InfoPlist(params).getName(), ! "Info.plist", ! I18N.getString("resource.app-info-plist"), ! TEMPLATE_INFO_PLIST_LITE, ! data, VERBOSE.fetchFrom(params), ! RESOURCE_DIR.fetchFrom(params))); ! w.close(); } private void writePkgInfo(File file) throws IOException { //hardcoded as it does not seem we need to change it ever String signature = "????"; ! try (Writer out = new BufferedWriter(new FileWriter(file))) { out.write(OS_TYPE_CODE + signature); out.flush(); } } --- 631,652 ---- } else { associationData = ""; } data.put("DEPLOY_FILE_ASSOCIATIONS", associationData); ! createResource(TEMPLATE_INFO_PLIST_LITE, params) ! .setCategory(I18N.getString("resource.app-info-plist")) ! .setSubstitutionData(data) ! .setPublicName("Info.plist") ! .saveToFile(file); } private void writePkgInfo(File file) throws IOException { //hardcoded as it does not seem we need to change it ever String signature = "????"; ! try (Writer out = Files.newBufferedWriter(file.toPath())) { out.write(OS_TYPE_CODE + signature); out.flush(); } }
*** 759,769 **** args.addAll(keyChains); args.add(keyChain); ProcessBuilder pb = new ProcessBuilder(args); ! IOUtils.exec(pb, false); } public static void restoreKeychainList(Map<String, ? super Object> params) throws IOException{ if (Platform.getMajorVersion() < 10 || --- 698,708 ---- args.addAll(keyChains); args.add(keyChain); ProcessBuilder pb = new ProcessBuilder(args); ! IOUtils.exec(pb); } public static void restoreKeychainList(Map<String, ? super Object> params) throws IOException{ if (Platform.getMajorVersion() < 10 ||
*** 783,793 **** args.add("-s"); args.addAll(keyChains); ProcessBuilder pb = new ProcessBuilder(args); ! IOUtils.exec(pb, false); } public static void signAppBundle( Map<String, ? super Object> params, Path appLocation, String signingIdentity, String identifierPrefix, --- 722,732 ---- args.add("-s"); args.addAll(keyChains); ProcessBuilder pb = new ProcessBuilder(args); ! IOUtils.exec(pb); } public static void signAppBundle( Map<String, ? super Object> params, Path appLocation, String signingIdentity, String identifierPrefix,
*** 796,837 **** AtomicReference<IOException> toThrow = new AtomicReference<>(); String appExecutable = "/Contents/MacOS/" + APP_NAME.fetchFrom(params); String keyChain = SIGNING_KEYCHAIN.fetchFrom(params); // sign all dylibs and jars ! Files.walk(appLocation) ! // fix permissions ! .peek(path -> { try { Set<PosixFilePermission> pfp = Files.getPosixFilePermissions(path); if (!pfp.contains(PosixFilePermission.OWNER_WRITE)) { pfp = EnumSet.copyOf(pfp); pfp.add(PosixFilePermission.OWNER_WRITE); Files.setPosixFilePermissions(path, pfp); } } catch (IOException e) { ! Log.debug(e); } ! }) ! .filter(p -> Files.isRegularFile(p) && ! !(p.toString().contains("/Contents/MacOS/libjli.dylib") ! || p.toString().contains( ! "/Contents/MacOS/JavaAppletPlugin") ! || p.toString().endsWith(appExecutable)) ! ).forEach(p -> { //noinspection ThrowableResultOfMethodCallIgnored if (toThrow.get() != null) return; // If p is a symlink then skip the signing process. if (Files.isSymbolicLink(p)) { if (VERBOSE.fetchFrom(params)) { Log.verbose(MessageFormat.format(I18N.getString( "message.ignoring.symlink"), p.toString())); } } ! else { List<String> args = new ArrayList<>(); args.addAll(Arrays.asList("codesign", "-s", signingIdentity, // sign with this key "--prefix", identifierPrefix, // use the identifier as a prefix --- 735,778 ---- AtomicReference<IOException> toThrow = new AtomicReference<>(); String appExecutable = "/Contents/MacOS/" + APP_NAME.fetchFrom(params); String keyChain = SIGNING_KEYCHAIN.fetchFrom(params); // sign all dylibs and jars ! try (Stream<Path> stream = Files.walk(appLocation)) { ! stream.peek(path -> { // fix permissions try { Set<PosixFilePermission> pfp = Files.getPosixFilePermissions(path); if (!pfp.contains(PosixFilePermission.OWNER_WRITE)) { pfp = EnumSet.copyOf(pfp); pfp.add(PosixFilePermission.OWNER_WRITE); Files.setPosixFilePermissions(path, pfp); } } catch (IOException e) { ! Log.verbose(e); } ! }).filter(p -> Files.isRegularFile(p) ! && !(p.toString().contains("/Contents/MacOS/libjli.dylib") ! || p.toString().endsWith(appExecutable) ! || p.toString().contains("/Contents/runtime") ! || p.toString().contains("/Contents/Frameworks"))).forEach(p -> { //noinspection ThrowableResultOfMethodCallIgnored if (toThrow.get() != null) return; // If p is a symlink then skip the signing process. if (Files.isSymbolicLink(p)) { if (VERBOSE.fetchFrom(params)) { Log.verbose(MessageFormat.format(I18N.getString( "message.ignoring.symlink"), p.toString())); } + } else { + if (p.toString().endsWith(LIBRARY_NAME)) { + if (isFileSigned(p)) { + return; } ! } ! List<String> args = new ArrayList<>(); args.addAll(Arrays.asList("codesign", "-s", signingIdentity, // sign with this key "--prefix", identifierPrefix, // use the identifier as a prefix
*** 858,876 **** Files.getPosixFilePermissions(p); File f = p.toFile(); f.setWritable(true, true); ProcessBuilder pb = new ProcessBuilder(args); ! IOUtils.exec(pb, false); Files.setPosixFilePermissions(p, oldPermissions); } catch (IOException ioe) { toThrow.set(ioe); } } }); ! IOException ioe = toThrow.get(); if (ioe != null) { throw ioe; } --- 799,817 ---- Files.getPosixFilePermissions(p); File f = p.toFile(); f.setWritable(true, true); ProcessBuilder pb = new ProcessBuilder(args); ! IOUtils.exec(pb); Files.setPosixFilePermissions(p, oldPermissions); } catch (IOException ioe) { toThrow.set(ioe); } } }); ! } IOException ioe = toThrow.get(); if (ioe != null) { throw ioe; }
*** 890,900 **** args.add("--keychain"); args.add(keyChain); } args.add(path.toString()); ProcessBuilder pb = new ProcessBuilder(args); ! IOUtils.exec(pb, false); args = new ArrayList<>(); args.addAll(Arrays.asList("codesign", "-s", signingIdentity, // sign with this key "--prefix", identifierPrefix, --- 831,841 ---- args.add("--keychain"); args.add(keyChain); } args.add(path.toString()); ProcessBuilder pb = new ProcessBuilder(args); ! IOUtils.exec(pb); args = new ArrayList<>(); args.addAll(Arrays.asList("codesign", "-s", signingIdentity, // sign with this key "--prefix", identifierPrefix,
*** 905,924 **** args.add(keyChain); } args.add(path.toString() + "/Contents/_CodeSignature/CodeResources"); pb = new ProcessBuilder(args); ! IOUtils.exec(pb, false); } catch (IOException e) { toThrow.set(e); } }; Path javaPath = appLocation.resolve("Contents/runtime"); if (Files.isDirectory(javaPath)) { ! Files.list(javaPath) ! .forEach(signIdentifiedByPList); ioe = toThrow.get(); if (ioe != null) { throw ioe; } --- 846,864 ---- args.add(keyChain); } args.add(path.toString() + "/Contents/_CodeSignature/CodeResources"); pb = new ProcessBuilder(args); ! IOUtils.exec(pb); } catch (IOException e) { toThrow.set(e); } }; Path javaPath = appLocation.resolve("Contents/runtime"); if (Files.isDirectory(javaPath)) { ! signIdentifiedByPList.accept(javaPath); ioe = toThrow.get(); if (ioe != null) { throw ioe; }
*** 949,957 **** } args.add(appLocation.toString()); ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[args.size()])); ! IOUtils.exec(pb, false); } } --- 889,945 ---- } args.add(appLocation.toString()); ProcessBuilder pb = new ProcessBuilder(args.toArray(new String[args.size()])); ! IOUtils.exec(pb); ! } ! ! private static boolean isFileSigned(Path file) { ! ProcessBuilder pb = ! new ProcessBuilder("codesign", "--verify", file.toString()); ! ! try { ! IOUtils.exec(pb); ! } catch (IOException ex) { ! return false; ! } ! ! return true; ! } ! ! private static String extractBundleIdentifier(Map<String, Object> params) { ! if (PREDEFINED_APP_IMAGE.fetchFrom(params) == null) { ! return null; ! } ! ! try { ! File infoPList = new File(PREDEFINED_APP_IMAGE.fetchFrom(params) + ! File.separator + "Contents" + ! File.separator + "Info.plist"); ! ! DocumentBuilderFactory dbf ! = DocumentBuilderFactory.newDefaultInstance(); ! dbf.setFeature("http://apache.org/xml/features/" + ! "nonvalidating/load-external-dtd", false); ! DocumentBuilder b = dbf.newDocumentBuilder(); ! org.w3c.dom.Document doc = b.parse(new FileInputStream( ! infoPList.getAbsolutePath())); ! ! XPath xPath = XPathFactory.newInstance().newXPath(); ! // Query for the value of <string> element preceding <key> ! // element with value equal to CFBundleIdentifier ! String v = (String) xPath.evaluate( ! "//string[preceding-sibling::key = \"CFBundleIdentifier\"][1]", ! doc, XPathConstants.STRING); ! ! if (v != null && !v.isEmpty()) { ! return v; ! } ! } catch (Exception ex) { ! Log.verbose(ex); ! } ! ! return null; } }
< prev index next >