diff -r f63f13da91c0 -r 1b08af362a30 src/jdk.packager/macosx/classes/jdk/packager/internal/mac/MacPkgBundler.java --- a/src/jdk.packager/macosx/classes/jdk/packager/internal/mac/MacPkgBundler.java Fri Nov 02 11:34:56 2018 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,603 +0,0 @@ -/* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * 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.packager.internal.mac; - -import jdk.packager.internal.BundlerParamInfo; -import jdk.packager.internal.StandardBundlerParam; -import jdk.packager.internal.Log; -import jdk.packager.internal.ConfigException; -import jdk.packager.internal.IOUtils; -import jdk.packager.internal.Platform; -import jdk.packager.internal.RelativeFileSet; -import jdk.packager.internal.UnsupportedPlatformException; -import jdk.packager.internal.resources.mac.MacResources; -import jdk.packager.internal.builders.mac.MacAppImageBuilder; -import jdk.packager.internal.Arguments; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintStream; -import java.io.Writer; -import java.net.URLEncoder; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.ResourceBundle; - -import static jdk.packager.internal.StandardBundlerParam.*; -import static - jdk.packager.internal.mac.MacBaseInstallerBundler.SIGNING_KEYCHAIN; -import static - jdk.packager.internal.mac.MacBaseInstallerBundler.SIGNING_KEY_USER; - -public class MacPkgBundler extends MacBaseInstallerBundler { - - private static final ResourceBundle I18N = ResourceBundle.getBundle( - "jdk.packager.internal.resources.mac.MacPkgBundler"); - - public final static String MAC_BUNDLER_PREFIX = - BUNDLER_PREFIX + "macosx" + File.separator; - - private static final String DEFAULT_BACKGROUND_IMAGE = "background_pkg.png"; - - private static final String TEMPLATE_PREINSTALL_SCRIPT = - "preinstall.template"; - private static final String TEMPLATE_POSTINSTALL_SCRIPT = - "postinstall.template"; - - private static final BundlerParamInfo PACKAGES_ROOT = - new StandardBundlerParam<>( - I18N.getString("param.packages-root.name"), - I18N.getString("param.packages-root.description"), - "mac.pkg.packagesRoot", - File.class, - params -> { - File packagesRoot = - new File(BUILD_ROOT.fetchFrom(params), "packages"); - packagesRoot.mkdirs(); - return packagesRoot; - }, - (s, p) -> new File(s)); - - - protected final BundlerParamInfo SCRIPTS_DIR = - new StandardBundlerParam<>( - I18N.getString("param.scripts-dir.name"), - I18N.getString("param.scripts-dir.description"), - "mac.pkg.scriptsDir", - File.class, - params -> { - File scriptsDir = - new File(CONFIG_ROOT.fetchFrom(params), "scripts"); - scriptsDir.mkdirs(); - return scriptsDir; - }, - (s, p) -> new File(s)); - - public static final - BundlerParamInfo DEVELOPER_ID_INSTALLER_SIGNING_KEY = - new StandardBundlerParam<>( - I18N.getString("param.signing-key-developer-id-installer.name"), - I18N.getString( - "param.signing-key-developer-id-installer.description"), - "mac.signing-key-developer-id-installer", - String.class, - params -> { - String result = MacBaseInstallerBundler.findKey( - "Developer ID Installer: " - + SIGNING_KEY_USER.fetchFrom(params), - SIGNING_KEYCHAIN.fetchFrom(params), - VERBOSE.fetchFrom(params)); - if (result != null) { - MacCertificate certificate = new MacCertificate( - result, VERBOSE.fetchFrom(params)); - - if (!certificate.isValid()) { - Log.info(MessageFormat.format( - I18N.getString("error.certificate.expired"), - result)); - } - } - - return result; - }, - (s, p) -> s); - - public static final BundlerParamInfo MAC_INSTALL_DIR = - new StandardBundlerParam<>( - I18N.getString("param.mac-install-dir.name"), - I18N.getString("param.mac-install-dir.description"), - "mac-install-dir", - String.class, - params -> { - String dir = INSTALL_DIR.fetchFrom(params); - return (dir != null) ? dir : "/Applications"; - }, - (s, p) -> s - ); - - public static final BundlerParamInfo INSTALLER_SUFFIX = - new StandardBundlerParam<> ( - I18N.getString("param.installer-suffix.name"), - I18N.getString("param.installer-suffix.description"), - "mac.pkg.installerName.suffix", - String.class, - params -> "", - (s, p) -> s); - - public MacPkgBundler() { - super(); - baseResourceLoader = MacResources.class; - } - - public File bundle(Map params, File outdir) { - Log.info(MessageFormat.format(I18N.getString("message.building-pkg"), - APP_NAME.fetchFrom(params))); - if (!outdir.isDirectory() && !outdir.mkdirs()) { - throw new RuntimeException(MessageFormat.format( - I18N.getString("error.cannot-create-output-dir"), - outdir.getAbsolutePath())); - } - if (!outdir.canWrite()) { - throw new RuntimeException(MessageFormat.format( - I18N.getString("error.cannot-write-to-output-dir"), - outdir.getAbsolutePath())); - } - - File appImageDir = null; - try { - appImageDir = prepareAppBundle(params, false); - - if (appImageDir != null && prepareConfigFiles(params)) { - - File configScript = getConfig_Script(params); - if (configScript.exists()) { - Log.info(MessageFormat.format(I18N.getString( - "message.running-script"), - configScript.getAbsolutePath())); - IOUtils.run("bash", configScript, false); - } - - return createPKG(params, outdir, appImageDir); - } - return null; - } catch (IOException ex) { - Log.verbose(ex); - return null; - } finally { - try { - if (appImageDir != null && - PREDEFINED_APP_IMAGE.fetchFrom(params) == null && - (PREDEFINED_RUNTIME_IMAGE.fetchFrom(params) == null || - !Arguments.CREATE_JRE_INSTALLER.fetchFrom(params)) && - !Log.isDebug()) { - IOUtils.deleteRecursive(appImageDir); - } else if (appImageDir != null) { - Log.info(MessageFormat.format(I18N.getString( - "message.intermediate-image-location"), - appImageDir.getAbsolutePath())); - } - - // cleanup - cleanupConfigFiles(params); - } catch (IOException ex) { - Log.debug(ex); - // noinspection ReturnInsideFinallyBlock - return null; - } - } - } - - private File getPackages_AppPackage(Map params) { - return new File(PACKAGES_ROOT.fetchFrom(params), - APP_FS_NAME.fetchFrom(params) + "-app.pkg"); - } - - private File getPackages_DaemonPackage(Map params) { - return new File(PACKAGES_ROOT.fetchFrom(params), - APP_FS_NAME.fetchFrom(params) + "-daemon.pkg"); - } - - private void cleanupPackagesFiles(Map params) { - if (getPackages_AppPackage(params) != null) { - getPackages_AppPackage(params).delete(); - } - if (getPackages_DaemonPackage(params) != null) { - getPackages_DaemonPackage(params).delete(); - } - } - - private File getConfig_DistributionXMLFile( - Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), "distribution.dist"); - } - - private File getConfig_BackgroundImage(Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), - APP_NAME.fetchFrom(params) + "-background.png"); - } - - private File getScripts_PreinstallFile(Map params) { - return new File(SCRIPTS_DIR.fetchFrom(params), "preinstall"); - } - - private File getScripts_PostinstallFile( - Map params) { - return new File(SCRIPTS_DIR.fetchFrom(params), "postinstall"); - } - - private void cleanupConfigFiles(Map params) { - if (getConfig_DistributionXMLFile(params) != null) { - getConfig_DistributionXMLFile(params).delete(); - } - if (getConfig_BackgroundImage(params) != null) { - getConfig_BackgroundImage(params).delete(); - } - } - - private String getAppIdentifier(Map params) { - return IDENTIFIER.fetchFrom(params); - } - - private String getDaemonIdentifier(Map params) { - return IDENTIFIER.fetchFrom(params) + ".daemon"; - } - - private void preparePackageScripts(Map params) - throws IOException { - Log.verbose(I18N.getString("message.preparing-scripts")); - - Map data = new HashMap<>(); - - data.put("DEPLOY_DAEMON_IDENTIFIER", getDaemonIdentifier(params)); - data.put("DEPLOY_LAUNCHD_PLIST_FILE", - IDENTIFIER.fetchFrom(params).toLowerCase() + ".launchd.plist"); - - Writer w = new BufferedWriter( - new FileWriter(getScripts_PreinstallFile(params))); - String content = preprocessTextResource(MAC_BUNDLER_PREFIX - + getScripts_PreinstallFile(params).getName(), - I18N.getString("resource.pkg-preinstall-script"), - TEMPLATE_PREINSTALL_SCRIPT, - data, - VERBOSE.fetchFrom(params), - DROP_IN_RESOURCES_ROOT.fetchFrom(params)); - w.write(content); - w.close(); - getScripts_PreinstallFile(params).setExecutable(true, false); - - w = new BufferedWriter( - new FileWriter(getScripts_PostinstallFile(params))); - content = preprocessTextResource(MAC_BUNDLER_PREFIX - + getScripts_PostinstallFile(params).getName(), - I18N.getString("resource.pkg-postinstall-script"), - TEMPLATE_POSTINSTALL_SCRIPT, - data, - VERBOSE.fetchFrom(params), - DROP_IN_RESOURCES_ROOT.fetchFrom(params)); - w.write(content); - w.close(); - getScripts_PostinstallFile(params).setExecutable(true, false); - } - - private void prepareDistributionXMLFile(Map params) - throws IOException { - File f = getConfig_DistributionXMLFile(params); - - Log.verbose(MessageFormat.format(I18N.getString( - "message.preparing-distribution-dist"), f.getAbsolutePath())); - - PrintStream out = new PrintStream(f); - - out.println( - ""); - out.println(""); - - out.println("" + APP_NAME.fetchFrom(params) + ""); - out.println(""); - - if (!LICENSE_FILE.fetchFrom(params).isEmpty()) { - File licFile = null; - - List licFiles = LICENSE_FILE.fetchFrom(params); - if (licFiles.isEmpty()) { - return; - } - String licFileStr = licFiles.get(0); - - for (RelativeFileSet rfs : APP_RESOURCES_LIST.fetchFrom(params)) { - if (rfs.contains(licFileStr)) { - licFile = new File(rfs.getBaseDirectory(), licFileStr); - break; - } - } - - // this is NPE protection, validate should have caught it's absence - // so we don't complain or throw an error - if (licFile != null) { - out.println(""); - } - } - - /* - * Note that the content of the distribution file - * below is generated by productbuild --synthesize - */ - - String appId = getAppIdentifier(params); - String daemonId = getDaemonIdentifier(params); - - out.println(""); - - out.println(""); - out.println(""); - out.println(" "); - out.println(" "); - out.println(" "); - out.println(""); - out.println(""); - out.println(""); - out.println(" "); - out.println(""); - out.println("" - + URLEncoder.encode(getPackages_AppPackage(params).getName(), - "UTF-8") + ""); - - out.println(""); - - out.close(); - } - - private boolean prepareConfigFiles(Map params) - throws IOException { - File imageTarget = getConfig_BackgroundImage(params); - fetchResource(MacAppBundler.MAC_BUNDLER_PREFIX + imageTarget.getName(), - I18N.getString("resource.pkg-background-image"), - DEFAULT_BACKGROUND_IMAGE, - imageTarget, - VERBOSE.fetchFrom(params), - DROP_IN_RESOURCES_ROOT.fetchFrom(params)); - - prepareDistributionXMLFile(params); - - fetchResource(MacAppBundler.MAC_BUNDLER_PREFIX - + getConfig_Script(params).getName(), - I18N.getString("resource.post-install-script"), - (String) null, - getConfig_Script(params), - VERBOSE.fetchFrom(params), - DROP_IN_RESOURCES_ROOT.fetchFrom(params)); - - return true; - } - - // name of post-image script - private File getConfig_Script(Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), - APP_NAME.fetchFrom(params) + "-post-image.sh"); - } - - private File createPKG(Map params, - File outdir, File appLocation) { - // generic find attempt - try { - File appPKG = getPackages_AppPackage(params); - - // build application package - ProcessBuilder pb = new ProcessBuilder("pkgbuild", - "--component", - appLocation.toString(), - "--install-location", - MAC_INSTALL_DIR.fetchFrom(params), - appPKG.getAbsolutePath()); - IOUtils.exec(pb, false); - - // build final package - File finalPKG = new File(outdir, INSTALLER_NAME.fetchFrom(params) - + INSTALLER_SUFFIX.fetchFrom(params) - + ".pkg"); - outdir.mkdirs(); - - List commandLine = new ArrayList<>(); - commandLine.add("productbuild"); - - commandLine.add("--resources"); - commandLine.add(CONFIG_ROOT.fetchFrom(params).getAbsolutePath()); - - // maybe sign - if (Optional.ofNullable(MacAppImageBuilder. - SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) { - if (Platform.getMajorVersion() > 10 || - (Platform.getMajorVersion() == 10 && - Platform.getMinorVersion() >= 12)) { - // we need this for OS X 10.12+ - Log.info(I18N.getString("message.signing.pkg")); - } - - String signingIdentity = - DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params); - if (signingIdentity != null) { - commandLine.add("--sign"); - commandLine.add(signingIdentity); - } - - String keychainName = SIGNING_KEYCHAIN.fetchFrom(params); - if (keychainName != null && !keychainName.isEmpty()) { - commandLine.add("--keychain"); - commandLine.add(keychainName); - } - } - - commandLine.add("--distribution"); - commandLine.add( - getConfig_DistributionXMLFile(params).getAbsolutePath()); - commandLine.add("--package-path"); - commandLine.add(PACKAGES_ROOT.fetchFrom(params).getAbsolutePath()); - - commandLine.add(finalPKG.getAbsolutePath()); - - pb = new ProcessBuilder(commandLine); - IOUtils.exec(pb, false); - - return finalPKG; - } catch (Exception ignored) { - Log.verbose(ignored); - return null; - } finally { - cleanupPackagesFiles(params); - cleanupConfigFiles(params); - } - } - - ////////////////////////////////////////////////////////////////////////// - // Implement Bundler - ////////////////////////////////////////////////////////////////////////// - - @Override - public String getName() { - return I18N.getString("bundler.name"); - } - - @Override - public String getDescription() { - return I18N.getString("bundler.description"); - } - - @Override - public String getID() { - return "pkg"; - } - - @Override - public Collection> getBundleParameters() { - Collection> results = new LinkedHashSet<>(); - results.addAll(MacAppBundler.getAppBundleParameters()); - results.addAll(getPKGBundleParameters()); - return results; - } - - public Collection> getPKGBundleParameters() { - Collection> results = new LinkedHashSet<>(); - - results.addAll(MacAppBundler.getAppBundleParameters()); - results.addAll(Arrays.asList( - DEVELOPER_ID_INSTALLER_SIGNING_KEY, - // IDENTIFIER, - INSTALLER_SUFFIX, - LICENSE_FILE, - // SERVICE_HINT, - SIGNING_KEYCHAIN)); - - return results; - } - - @Override - public boolean validate(Map params) - throws UnsupportedPlatformException, ConfigException { - try { - if (params == null) throw new ConfigException( - I18N.getString("error.parameters-null"), - I18N.getString("error.parameters-null.advice")); - - // run basic validation to ensure requirements are met - // we are not interested in return code, only possible exception - validateAppImageAndBundeler(params); - - // validate license file, if used, exists in the proper place - if (params.containsKey(LICENSE_FILE.getID())) { - List appResourcesList = - APP_RESOURCES_LIST.fetchFrom(params); - for (String license : LICENSE_FILE.fetchFrom(params)) { - boolean found = false; - for (RelativeFileSet appResources : appResourcesList) { - found = found || appResources.contains(license); - } - if (!found) { - throw new ConfigException( - I18N.getString("error.license-missing"), - MessageFormat.format( - I18N.getString("error.license-missing.advice"), - license)); - } - } - } - - // reject explicitly set sign to true and no valid signature key - if (Optional.ofNullable(MacAppImageBuilder. - SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) { - String signingIdentity = - DEVELOPER_ID_INSTALLER_SIGNING_KEY.fetchFrom(params); - if (signingIdentity == null) { - throw new ConfigException( - I18N.getString("error.explicit-sign-no-cert"), - I18N.getString( - "error.explicit-sign-no-cert.advice")); - } - } - - // hdiutil is always available so there's no need - // to test for availability. - - return true; - } catch (RuntimeException re) { - if (re.getCause() instanceof ConfigException) { - throw (ConfigException) re.getCause(); - } else { - throw new ConfigException(re); - } - } - } - - @Override - public File execute( - Map params, File outputParentDir) { - return bundle(params, outputParentDir); - } - - @Override - public boolean supported() { - return Platform.getPlatform() == Platform.MAC; - } - -}