--- old/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/OverridableResource.java 2019-12-13 13:34:14.247777000 -0500 +++ new/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/OverridableResource.java 2019-12-13 13:34:13.217148600 -0500 @@ -30,10 +30,7 @@ import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.text.MessageFormat; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; import static jdk.incubator.jpackage.internal.StandardBundlerParam.RESOURCE_DIR; @@ -64,6 +61,7 @@ OverridableResource(String defaultName) { this.defaultName = defaultName; + setSourceOrder(Source.values()); } OverridableResource setSubstitutionData(Map v) { @@ -90,6 +88,15 @@ return setResourceDir(toPath(v)); } + enum Source { External, ResourceDir, DefaultResource }; + + OverridableResource setSourceOrder(Source... v) { + sources = Stream.of(v) + .map(source -> Map.entry(source, getHandler(source))) + .collect(Collectors.toList()); + return this; + } + /** * Set name of file to look for in resource dir. * @@ -104,6 +111,20 @@ return setPublicName(Path.of(v)); } + /** + * Set name of file to look for in resource dir to put in verbose log. + * + * @return this + */ + OverridableResource setLogPublicName(Path v) { + logPublicName = v; + return this; + } + + OverridableResource setLogPublicName(String v) { + return setLogPublicName(Path.of(v)); + } + OverridableResource setExternal(Path v) { externalPath = v; return this; @@ -113,67 +134,102 @@ return setExternal(toPath(v)); } - void saveToFile(Path dest) throws IOException { - final String printableCategory; + Source saveToFile(Path dest) throws IOException { + for (var source: sources) { + if (source.getValue().apply(dest)) { + return source.getKey(); + } + } + return null; + } + + Source saveToFile(File dest) throws IOException { + return saveToFile(toPath(dest)); + } + + static InputStream readDefault(String resourceName) { + return ResourceLocator.class.getResourceAsStream(resourceName); + } + + static OverridableResource createResource(String defaultName, + Map params) { + return new OverridableResource(defaultName).setResourceDir( + RESOURCE_DIR.fetchFrom(params)); + } + + private String getPrintableCategory() { if (category != null) { - printableCategory = String.format("[%s]", category); - } else { - printableCategory = ""; + return String.format("[%s]", category); } + return ""; + } - if (externalPath != null && externalPath.toFile().exists()) { + private boolean useExternal(Path dest) throws IOException { + boolean used = externalPath != null && Files.exists(externalPath); + if (used && dest != null) { Log.verbose(MessageFormat.format(I18N.getString( "message.using-custom-resource-from-file"), - printableCategory, + getPrintableCategory(), externalPath.toAbsolutePath().normalize())); try (InputStream in = Files.newInputStream(externalPath)) { processResourceStream(in, dest); } - return; + } + return used; + } + + private boolean useResourceDir(Path dest) throws IOException { + boolean used = false; + + if (dest == null && publicName == null) { + throw new IllegalStateException(); } - final Path resourceName = Optional.ofNullable(publicName).orElse( - dest.getFileName()); + final Path resourceName = Optional.ofNullable(publicName).orElseGet( + () -> dest.getFileName()); if (resourceDir != null) { final Path customResource = resourceDir.resolve(resourceName); - if (customResource.toFile().exists()) { + used = Files.exists(customResource); + if (used && dest != null) { + final Path logResourceName; + if (logPublicName != null) { + logResourceName = logPublicName.normalize(); + } else { + logResourceName = resourceName.normalize(); + } + Log.verbose(MessageFormat.format(I18N.getString( - "message.using-custom-resource"), printableCategory, - resourceDir.normalize().toAbsolutePath().relativize( - customResource.normalize().toAbsolutePath()))); + "message.using-custom-resource"), getPrintableCategory(), + logResourceName)); try (InputStream in = Files.newInputStream(customResource)) { processResourceStream(in, dest); } - return; } } - if (defaultName != null) { + return used; + } + + private boolean useDefault(Path dest) throws IOException { + boolean used = defaultName != null; + if (used && dest != null) { + final Path resourceName = Optional + .ofNullable(logPublicName) + .orElse(Optional + .ofNullable(publicName) + .orElseGet(() -> dest.getFileName())); Log.verbose(MessageFormat.format( I18N.getString("message.using-default-resource"), - defaultName, printableCategory, resourceName)); + defaultName, getPrintableCategory(), resourceName)); try (InputStream in = readDefault(defaultName)) { processResourceStream(in, dest); } } - } - - void saveToFile(File dest) throws IOException { - saveToFile(dest.toPath()); - } - - static InputStream readDefault(String resourceName) { - return ResourceLocator.class.getResourceAsStream(resourceName); - } - - static OverridableResource createResource(String defaultName, - Map params) { - return new OverridableResource(defaultName).setResourceDir( - RESOURCE_DIR.fetchFrom(params)); + return used; } private static List substitute(Stream lines, @@ -210,10 +266,33 @@ } } + private SourceHandler getHandler(Source sourceType) { + switch (sourceType) { + case DefaultResource: + return this::useDefault; + + case External: + return this::useExternal; + + case ResourceDir: + return this::useResourceDir; + + default: + throw new IllegalArgumentException(); + } + } + private Map substitutionData; private String category; private Path resourceDir; private Path publicName; + private Path logPublicName; private Path externalPath; private final String defaultName; + private List> sources; + + @FunctionalInterface + static interface SourceHandler { + public boolean apply(Path dest) throws IOException; + } }