diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java index fd637b290414..d95beaa8ca29 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java @@ -103,6 +103,24 @@ public static void registerResource(String name, InputStream is) { list.add(res); } + @Platforms(Platform.HOSTED_ONLY.class) + public static void registerDirectoryResource(String dir, String content) { + /* + * A directory content represents the names of all files and subdirectories located in the + * specified directory, separated with new line delimiter and joined into one string which + * is later converted into a byte array and placed into the resources map. + */ + ResourcesSupport support = ImageSingletons.lookup(ResourcesSupport.class); + + byte[] arr = content.getBytes(); + List list = support.resources.get(dir); + if (list == null) { + list = new ArrayList<>(); + support.resources.put(dir, list); + } + list.add(arr); + } + public static List get(String name) { return ImageSingletons.lookup(ResourcesSupport.class).resources.get(name); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java index 86f26dc8aea6..629088b85f31 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java @@ -32,10 +32,15 @@ import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.Enumeration; +import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.jar.JarEntry; @@ -207,17 +212,40 @@ private void scanDirectory(DebugContext debugContext, File f, String relativePat private static void scanJar(DebugContext debugContext, File element, Pattern... patterns) throws IOException { JarFile jf = new JarFile(element); Enumeration en = jf.entries(); + + Map> matchedDirectoryResources = new HashMap<>(); + Set allEntries = new HashSet<>(); while (en.hasMoreElements()) { JarEntry e = en.nextElement(); - if (e.getName().endsWith("/")) { + if (e.isDirectory()) { + String dirName = e.getName().substring(0, e.getName().length() - 1); + allEntries.add(dirName); + if (matches(patterns, dirName)) { + matchedDirectoryResources.put(dirName, new ArrayList<>()); + } continue; } + allEntries.add(e.getName()); if (matches(patterns, e.getName())) { try (InputStream is = jf.getInputStream(e)) { registerResource(debugContext, e.getName(), is); } } } + + for (String entry : allEntries) { + int last = entry.lastIndexOf('/'); + String key = last == -1 ? "" : entry.substring(0, last); + List dirContent = matchedDirectoryResources.get(key); + if (dirContent != null && !dirContent.contains(entry)) { + dirContent.add(entry.substring(last + 1, entry.length())); + } + } + + matchedDirectoryResources.forEach((dir, content) -> { + content.sort(Comparator.naturalOrder()); + registerDirectoryResource(debugContext, dir, String.join(System.lineSeparator(), content)); + }); } private static boolean matches(Pattern[] patterns, String relativePath) { @@ -236,4 +264,12 @@ private static void registerResource(DebugContext debugContext, String resourceN Resources.registerResource(resourceName, resourceStream); } } + + @SuppressWarnings("try") + private static void registerDirectoryResource(DebugContext debugContext, String dir, String content) { + try (DebugContext.Scope s = debugContext.scope("registerResource")) { + debugContext.log(DebugContext.VERBOSE_LEVEL, "ResourcesFeature: registerResource: " + dir); + Resources.registerDirectoryResource(dir, content); + } + } }