12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package jdk.jpackage.test; 24 25 import java.io.ByteArrayInputStream; 26 import java.io.IOException; 27 import java.nio.charset.StandardCharsets; 28 import java.nio.file.Files; 29 import java.nio.file.Path; 30 import java.util.List; 31 import java.util.Set; 32 import java.util.stream.Collectors; 33 import java.util.stream.Stream; 34 import javax.xml.parsers.DocumentBuilder; 35 import javax.xml.parsers.DocumentBuilderFactory; 36 import javax.xml.parsers.ParserConfigurationException; 37 import javax.xml.xpath.XPath; 38 import javax.xml.xpath.XPathConstants; 39 import javax.xml.xpath.XPathFactory; 40 import jdk.jpackage.test.Functional.ThrowingConsumer; 41 import jdk.jpackage.test.Functional.ThrowingSupplier; 42 import org.xml.sax.SAXException; 43 44 public class MacHelper { 45 46 public static void withExplodedDmg(JPackageCommand cmd, 47 ThrowingConsumer<Path> consumer) { 48 cmd.verifyIsOfType(PackageType.MAC_DMG); 49 50 var plist = readPList(new Executor() 51 .setExecutable("/usr/bin/hdiutil") 52 .dumpOutput() 53 .addArguments("attach", cmd.outputBundle().toString(), "-plist") 54 .executeAndGetOutput()); 55 56 final Path mountPoint = Path.of(plist.queryValue("mount-point")); 57 try { 58 Path dmgImage = mountPoint.resolve(cmd.name() + ".app"); 59 TKit.trace(String.format("Exploded [%s] in [%s] directory", 60 cmd.outputBundle(), dmgImage)); 61 ThrowingConsumer.toConsumer(consumer).accept(dmgImage); 62 } finally { 63 new Executor() 64 .setExecutable("/usr/bin/hdiutil") 65 .addArgument("detach").addArgument(mountPoint) 66 .execute().assertExitCodeIsZero(); 67 } 68 } 69 70 public static PListWrapper readPListFromAppImage(Path appImage) { 71 return readPList(appImage.resolve("Contents/Info.plist")); 72 } 73 74 public static PListWrapper readPList(Path path) { 75 TKit.assertReadableFileExists(path); 76 return ThrowingSupplier.toSupplier(() -> readPList(Files.readAllLines( 77 path))).get(); 78 } 79 80 public static PListWrapper readPList(List<String> lines) { 81 return readPList(lines.stream()); 82 } 83 84 public static PListWrapper readPList(Stream<String> lines) { 85 return ThrowingSupplier.toSupplier(() -> new PListWrapper(lines.collect( 86 Collectors.joining()))).get(); 87 } 88 89 static String getBundleName(JPackageCommand cmd) { 90 cmd.verifyIsOfType(PackageType.MAC); 91 return String.format("%s-%s%s", getPackageName(cmd), cmd.version(), 92 cmd.packageType().getSuffix()); 93 } 94 95 static Path getInstallationDirectory(JPackageCommand cmd) { 96 cmd.verifyIsOfType(PackageType.MAC); 97 return Path.of(cmd.getArgumentValue("--install-dir", () -> "/Applications")) 98 .resolve(cmd.name() + ".app"); 99 } 100 101 private static String getPackageName(JPackageCommand cmd) { 102 return cmd.getArgumentValue("--mac-package-name", 103 () -> cmd.name()); 104 } 105 106 public static final class PListWrapper { | 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package jdk.jpackage.test; 24 25 import java.io.ByteArrayInputStream; 26 import java.io.IOException; 27 import java.nio.charset.StandardCharsets; 28 import java.nio.file.Files; 29 import java.nio.file.Path; 30 import java.util.List; 31 import java.util.Set; 32 import java.util.regex.Pattern; 33 import java.util.stream.Collectors; 34 import java.util.stream.Stream; 35 import javax.xml.parsers.DocumentBuilder; 36 import javax.xml.parsers.DocumentBuilderFactory; 37 import javax.xml.parsers.ParserConfigurationException; 38 import javax.xml.xpath.XPath; 39 import javax.xml.xpath.XPathConstants; 40 import javax.xml.xpath.XPathFactory; 41 import jdk.jpackage.test.Functional.ThrowingConsumer; 42 import jdk.jpackage.test.Functional.ThrowingSupplier; 43 import jdk.jpackage.test.PackageTest.PackageHandlers; 44 import org.xml.sax.SAXException; 45 46 public class MacHelper { 47 48 public static void withExplodedDmg(JPackageCommand cmd, 49 ThrowingConsumer<Path> consumer) { 50 cmd.verifyIsOfType(PackageType.MAC_DMG); 51 52 // Explode DMG assuming this can require interaction, thus use `yes`. 53 var plist = readPList(Executor.of("sh", "-c", 54 String.join(" ", "yes", "|", "/usr/bin/hdiutil", "attach", 55 JPackageCommand.escapeAndJoin( 56 cmd.outputBundle().toString()), "-plist")) 57 .dumpOutput() 58 .executeAndGetOutput()); 59 60 final Path mountPoint = Path.of(plist.queryValue("mount-point")); 61 try { 62 Path dmgImage = mountPoint.resolve(cmd.name() + ".app"); 63 TKit.trace(String.format("Exploded [%s] in [%s] directory", 64 cmd.outputBundle(), dmgImage)); 65 ThrowingConsumer.toConsumer(consumer).accept(dmgImage); 66 } finally { 67 Executor.of("/usr/bin/hdiutil", "detach").addArgument(mountPoint).execute(); 68 } 69 } 70 71 public static PListWrapper readPListFromAppImage(Path appImage) { 72 return readPList(appImage.resolve("Contents/Info.plist")); 73 } 74 75 public static PListWrapper readPList(Path path) { 76 TKit.assertReadableFileExists(path); 77 return ThrowingSupplier.toSupplier(() -> readPList(Files.readAllLines( 78 path))).get(); 79 } 80 81 public static PListWrapper readPList(List<String> lines) { 82 return readPList(lines.stream()); 83 } 84 85 public static PListWrapper readPList(Stream<String> lines) { 86 return ThrowingSupplier.toSupplier(() -> new PListWrapper(lines 87 // Skip leading lines before xml declaration 88 .dropWhile(Pattern.compile("\\s?<\\?xml\\b.+\\?>").asPredicate().negate()) 89 .collect(Collectors.joining()))).get(); 90 } 91 92 static PackageHandlers createDmgPackageHandlers() { 93 PackageHandlers dmg = new PackageHandlers(); 94 95 dmg.installHandler = cmd -> { 96 withExplodedDmg(cmd, dmgImage -> { 97 Executor.of("sudo", "cp", "-r") 98 .addArgument(dmgImage) 99 .addArgument("/Applications") 100 .execute(); 101 }); 102 }; 103 dmg.unpackHandler = (cmd, destinationDir) -> { 104 Path[] unpackedFolder = new Path[1]; 105 withExplodedDmg(cmd, dmgImage -> { 106 Executor.of("cp", "-r") 107 .addArgument(dmgImage) 108 .addArgument(destinationDir) 109 .execute(); 110 unpackedFolder[0] = destinationDir.resolve(dmgImage.getFileName()); 111 }); 112 return unpackedFolder[0]; 113 }; 114 dmg.uninstallHandler = cmd -> { 115 cmd.verifyIsOfType(PackageType.MAC_DMG); 116 Executor.of("sudo", "rm", "-rf") 117 .addArgument(cmd.appInstallationDirectory()) 118 .execute(); 119 }; 120 121 return dmg; 122 } 123 124 static PackageHandlers createPkgPackageHandlers() { 125 PackageHandlers pkg = new PackageHandlers(); 126 127 pkg.installHandler = cmd -> { 128 cmd.verifyIsOfType(PackageType.MAC_PKG); 129 Executor.of("sudo", "/usr/sbin/installer", "-allowUntrusted", "-pkg") 130 .addArgument(cmd.outputBundle()) 131 .addArguments("-target", "/") 132 .execute(); 133 }; 134 pkg.uninstallHandler = cmd -> { 135 cmd.verifyIsOfType(PackageType.MAC_PKG); 136 Executor.of("sudo", "rm", "-rf") 137 .addArgument(cmd.appInstallationDirectory()) 138 .execute(); 139 }; 140 141 return pkg; 142 } 143 144 static String getBundleName(JPackageCommand cmd) { 145 cmd.verifyIsOfType(PackageType.MAC); 146 return String.format("%s-%s%s", getPackageName(cmd), cmd.version(), 147 cmd.packageType().getSuffix()); 148 } 149 150 static Path getInstallationDirectory(JPackageCommand cmd) { 151 cmd.verifyIsOfType(PackageType.MAC); 152 return Path.of(cmd.getArgumentValue("--install-dir", () -> "/Applications")) 153 .resolve(cmd.name() + ".app"); 154 } 155 156 private static String getPackageName(JPackageCommand cmd) { 157 return cmd.getArgumentValue("--mac-package-name", 158 () -> cmd.name()); 159 } 160 161 public static final class PListWrapper { |