< prev index next >
src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java
Print this page
*** 28,57 ****
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
! import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.DESCRIPTION;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.LICENSE_FILE;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.TEMP_ROOT;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VENDOR;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VERSION;
/**
* WinMsiBundler
*
* Produces .msi installer from application image. Uses WiX Toolkit to build
--- 28,73 ----
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+ import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
! import java.nio.file.PathMatcher;
import java.text.MessageFormat;
+ import java.util.ArrayList;
import java.util.Arrays;
+ import java.util.Collections;
import java.util.HashMap;
+ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+ import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+ import javax.xml.parsers.DocumentBuilder;
+ import javax.xml.parsers.DocumentBuilderFactory;
+ import javax.xml.parsers.ParserConfigurationException;
+ import javax.xml.xpath.XPath;
+ import javax.xml.xpath.XPathConstants;
+ import javax.xml.xpath.XPathExpressionException;
+ import javax.xml.xpath.XPathFactory;
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.DESCRIPTION;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.LICENSE_FILE;
+ import static jdk.incubator.jpackage.internal.StandardBundlerParam.RESOURCE_DIR;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.TEMP_ROOT;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VENDOR;
import static jdk.incubator.jpackage.internal.StandardBundlerParam.VERSION;
+ import org.w3c.dom.Document;
+ import org.w3c.dom.NodeList;
+ import org.xml.sax.SAXException;
/**
* WinMsiBundler
*
* Produces .msi installer from application image. Uses WiX Toolkit to build
*** 414,424 ****
try (InputStream is = OverridableResource.readDefault(fname)) {
Files.copy(is, CONFIG_ROOT.fetchFrom(params).resolve(fname));
}
}
! // Copy l10n files.
for (String loc : Arrays.asList("en", "ja", "zh_CN")) {
String fname = "MsiInstallerStrings_" + loc + ".wxl";
try (InputStream is = OverridableResource.readDefault(fname)) {
Files.copy(is, CONFIG_ROOT.fetchFrom(params).resolve(fname));
}
--- 430,440 ----
try (InputStream is = OverridableResource.readDefault(fname)) {
Files.copy(is, CONFIG_ROOT.fetchFrom(params).resolve(fname));
}
}
! // Copy standard l10n files.
for (String loc : Arrays.asList("en", "ja", "zh_CN")) {
String fname = "MsiInstallerStrings_" + loc + ".wxl";
try (InputStream is = OverridableResource.readDefault(fname)) {
Files.copy(is, CONFIG_ROOT.fetchFrom(params).resolve(fname));
}
*** 468,480 ****
}
if (enableLicenseUI || enableInstalldirUI) {
wixPipeline.addLightOptions("-ext", "WixUIExtension");
}
! wixPipeline.addLightOptions("-loc",
! CONFIG_ROOT.fetchFrom(params).resolve(I18N.getString(
! "resource.wxl-file-name")).toAbsolutePath().toString());
// Only needed if we using CA dll, so Wix can find it
if (enableInstalldirUI) {
wixPipeline.addLightOptions("-b", CONFIG_ROOT.fetchFrom(params)
.toAbsolutePath().toString());
--- 484,510 ----
}
if (enableLicenseUI || enableInstalldirUI) {
wixPipeline.addLightOptions("-ext", "WixUIExtension");
}
! final Path primaryWxlFile = CONFIG_ROOT.fetchFrom(params).resolve(
! I18N.getString("resource.wxl-file-name")).toAbsolutePath();
!
! wixPipeline.addLightOptions("-loc", primaryWxlFile.toString());
!
! List<String> cultures = new ArrayList<>();
! for (var wxl : getCustomWxlFiles(params)) {
! wixPipeline.addLightOptions("-loc", wxl.toAbsolutePath().toString());
! cultures.add(getCultureFromWxlFile(wxl));
! }
! cultures.add(getCultureFromWxlFile(primaryWxlFile));
!
! // Build ordered list of unique cultures.
! Set<String> uniqueCultures = new LinkedHashSet<>();
! uniqueCultures.addAll(cultures);
! wixPipeline.addLightOptions(uniqueCultures.stream().collect(
! Collectors.joining(";", "-cultures:", "")));
// Only needed if we using CA dll, so Wix can find it
if (enableInstalldirUI) {
wixPipeline.addLightOptions("-b", CONFIG_ROOT.fetchFrom(params)
.toAbsolutePath().toString());
*** 483,492 ****
--- 513,568 ----
wixPipeline.buildMsi(msiOut.toAbsolutePath());
return msiOut;
}
+ private static List<Path> getCustomWxlFiles(Map<String, ? super Object> params)
+ throws IOException {
+ Path resourceDir = RESOURCE_DIR.fetchFrom(params);
+ if (resourceDir == null) {
+ return Collections.emptyList();
+ }
+
+ final String glob = "glob:**/*.wxl";
+ final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(
+ glob);
+
+ try (var walk = Files.walk(resourceDir, 1)) {
+ return walk
+ .filter(Files::isReadable)
+ .filter(pathMatcher::matches)
+ .sorted((a, b) -> a.getFileName().toString().compareToIgnoreCase(b.getFileName().toString()))
+ .collect(Collectors.toList());
+ }
+ }
+
+ private static String getCultureFromWxlFile(Path wxlPath) throws IOException {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(false);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+
+ Document doc = builder.parse(wxlPath.toFile());
+
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ NodeList nodes = (NodeList) xPath.evaluate(
+ "//WixLocalization/@Culture", doc,
+ XPathConstants.NODESET);
+ if (nodes.getLength() != 1) {
+ throw new IOException(MessageFormat.format(I18N.getString(
+ "error.extract-culture-from-wix-l10n-file"),
+ wxlPath.toAbsolutePath()));
+ }
+
+ return nodes.item(0).getNodeValue();
+ } catch (XPathExpressionException | ParserConfigurationException
+ | SAXException ex) {
+ throw new IOException(MessageFormat.format(I18N.getString(
+ "error.read-wix-l10n-file"), wxlPath.toAbsolutePath()), ex);
+ }
+ }
+
private static void ensureByMutationFileIsRTF(Path f) {
if (f == null || !Files.isRegularFile(f)) return;
try {
boolean existingLicenseIsRTF = false;
< prev index next >