1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.incubator.jpackage.internal; 27 28 import java.io.IOException; 29 import java.nio.file.Files; 30 import java.nio.file.Path; 31 import java.util.*; 32 import java.util.function.UnaryOperator; 33 import java.util.stream.Stream; 34 35 /** 36 * WiX pipeline. Compiles and links WiX sources. 37 */ 38 public class WixPipeline { 39 WixPipeline() { 40 sources = new ArrayList<>(); 41 lightOptions = new ArrayList<>(); 42 } 43 44 WixPipeline setToolset(Map<WixTool, Path> v) { 45 toolset = v; 46 return this; 47 } 48 49 WixPipeline setWixVariables(Map<String, String> v) { 50 wixVariables = v; 51 return this; 52 } 53 54 WixPipeline setWixObjDir(Path v) { 55 wixObjDir = v; 56 return this; 57 } 58 59 WixPipeline setWorkDir(Path v) { 60 workDir = v; 61 return this; 62 } 63 64 WixPipeline addSource(Path source, Map<String, String> wixVariables) { 65 WixSource entry = new WixSource(); 66 entry.source = source; 67 entry.variables = wixVariables; 68 sources.add(entry); 69 return this; 70 } 71 72 WixPipeline addLightOptions(String ... v) { 73 lightOptions.addAll(List.of(v)); 74 return this; 75 } 76 77 void buildMsi(Path msi) throws IOException { 78 List<Path> wixObjs = new ArrayList<>(); 79 for (var source : sources) { 80 wixObjs.add(compile(source)); 81 } 82 83 List<String> lightCmdline = new ArrayList<>(List.of( 84 toolset.get(WixTool.Light).toString(), 85 "-nologo", 86 "-spdb", 87 "-ext", "WixUtilExtension", 88 "-out", msi.toString() 89 )); 90 91 lightCmdline.addAll(lightOptions); 92 wixObjs.stream().map(Path::toString).forEach(lightCmdline::add); 93 94 Files.createDirectories(msi.getParent()); 95 execute(lightCmdline); 96 } 97 98 private Path compile(WixSource wixSource) throws IOException { 99 UnaryOperator<Path> adjustPath = path -> { 100 return workDir != null ? path.toAbsolutePath() : path; 101 }; 102 103 Path wixObj = adjustPath.apply(wixObjDir).resolve(IOUtils.replaceSuffix( 104 wixSource.source.getFileName(), ".wixobj")); 105 106 List<String> cmdline = new ArrayList<>(List.of( 107 toolset.get(WixTool.Candle).toString(), 108 "-nologo", 109 adjustPath.apply(wixSource.source).toString(), 110 "-ext", "WixUtilExtension", 111 "-arch", "x64", 112 "-out", wixObj.toAbsolutePath().toString() 113 )); 114 115 Map<String, String> appliedVaribales = new HashMap<>(); 116 Stream.of(wixVariables, wixSource.variables) 117 .filter(Objects::nonNull) 118 .forEachOrdered(appliedVaribales::putAll); 119 120 appliedVaribales.entrySet().stream().map(wixVar -> String.format("-d%s=%s", 121 wixVar.getKey(), wixVar.getValue())).forEachOrdered( 122 cmdline::add); 123 124 execute(cmdline); 125 126 return wixObj; 127 } 128 129 private void execute(List<String> cmdline) throws IOException { 130 Executor.of(new ProcessBuilder(cmdline).directory( 131 workDir != null ? workDir.toFile() : null)).executeExpectSuccess(); 132 } 133 134 private final static class WixSource { 135 Path source; 136 Map<String, String> variables; 137 } 138 139 private Map<WixTool, Path> toolset; 140 private Map<String, String> wixVariables; 141 private List<String> lightOptions; 142 private Path wixObjDir; 143 private Path workDir; 144 private List<WixSource> sources; 145 }