Skip to content

Commit 57dd966

Browse files
committed
typeReached for resources
1 parent fce88fc commit 57dd966

File tree

16 files changed

+124
-85
lines changed

16 files changed

+124
-85
lines changed

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/hosted/RuntimeResourceAccess.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ public static void addResource(Module module, String resourcePath, byte[] resour
8383
Objects.requireNonNull(module);
8484
Objects.requireNonNull(resourcePath);
8585
Objects.requireNonNull(resourceContent);
86-
ImageSingletons.lookup(RuntimeResourceSupport.class).injectResource(
87-
module, resourcePath, resourceContent);
86+
ImageSingletons.lookup(RuntimeResourceSupport.class).injectResource(module, resourcePath, resourceContent);
87+
ImageSingletons.lookup(RuntimeResourceSupport.class).addCondition(ConfigurationCondition.alwaysTrue(), module, resourcePath);
8888
}
8989

9090
/**

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/RuntimeResourceSupport.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,27 @@ static RuntimeResourceSupport<ConfigurationCondition> singleton() {
5454

5555
void addResources(C condition, String pattern);
5656

57-
void addResource(Module module, String resourcePath);
58-
5957
void addGlob(C condition, String module, String glob);
6058

61-
void injectResource(Module module, String resourcePath, byte[] resourceContent);
62-
6359
void ignoreResources(C condition, String pattern);
6460

6561
void addResourceBundles(C condition, String name);
6662

6763
void addResourceBundles(C condition, String basename, Collection<Locale> locales);
64+
65+
/* Following functions are used only from features */
66+
void addCondition(ConfigurationCondition configurationCondition, Module module, String resourcePath);
67+
68+
void addResourceEntry(Module module, String resourcePath);
69+
70+
default void addResource(Module module, String resourcePath) {
71+
addResource(ConfigurationCondition.alwaysTrue(), module, resourcePath);
72+
}
73+
74+
default void addResource(ConfigurationCondition condition, Module module, String resourcePath) {
75+
addResourceEntry(module, resourcePath);
76+
addCondition(condition, module, resourcePath);
77+
}
78+
79+
void injectResource(Module module, String resourcePath, byte[] resourceContent);
6880
}

substratevm/src/com.oracle.svm.configure.test/src/com/oracle/svm/configure/test/config/ResourceConfigurationTest.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.List;
3434
import java.util.Locale;
3535

36+
import org.graalvm.nativeimage.impl.ConfigurationCondition;
3637
import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition;
3738
import org.junit.Assert;
3839
import org.junit.Test;
@@ -102,7 +103,7 @@ public void addGlob(UnresolvedConfigurationCondition condition, String module, S
102103
}
103104

104105
@Override
105-
public void addResource(Module module, String resourcePath) {
106+
public void addResourceEntry(Module module, String resourcePath) {
106107
throw VMError.shouldNotReachHere("Unused function.");
107108
}
108109

@@ -124,6 +125,11 @@ public void addResourceBundles(UnresolvedConfigurationCondition condition, Strin
124125

125126
}
126127

128+
@Override
129+
public void addCondition(ConfigurationCondition configurationCondition, Module module, String resourcePath) {
130+
131+
}
132+
127133
@Override
128134
public void addClassBasedResourceBundle(UnresolvedConfigurationCondition condition, String basename, String className) {
129135

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ResourceConfiguration.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.util.concurrent.ConcurrentMap;
3636
import java.util.regex.Pattern;
3737

38+
import org.graalvm.nativeimage.impl.ConfigurationCondition;
3839
import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition;
3940

4041
import com.oracle.svm.configure.ConfigurationBase;
@@ -69,7 +70,12 @@ public void addGlob(UnresolvedConfigurationCondition condition, String module, S
6970
}
7071

7172
@Override
72-
public void addResource(Module module, String resourcePath) {
73+
public void addResourceEntry(Module module, String resourcePath) {
74+
throw VMError.shouldNotReachHere("Unused function.");
75+
}
76+
77+
@Override
78+
public void addCondition(ConfigurationCondition condition, Module module, String resourcePath) {
7379
throw VMError.shouldNotReachHere("Unused function.");
7480
}
7581

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/ClassLoaderSupport.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public boolean isNativeImageClassLoader(ClassLoader classLoader) {
5555
public interface ResourceCollector {
5656
List<ConfigurationCondition> isIncluded(Module module, String resourceName, URI resourceURI);
5757

58-
void addResource(Module module, String resourceName);
58+
void addResourceEntry(Module module, String resourceName);
5959

6060
void addResourceConditionally(Module module, String resourceName, ConfigurationCondition condition);
6161

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,13 @@
4747
import org.graalvm.nativeimage.ImageSingletons;
4848
import org.graalvm.nativeimage.Platform;
4949
import org.graalvm.nativeimage.Platforms;
50+
import org.graalvm.nativeimage.impl.ConfigurationCondition;
5051

5152
import com.oracle.svm.core.BuildPhaseProvider;
5253
import com.oracle.svm.core.MissingRegistrationUtils;
5354
import com.oracle.svm.core.SubstrateOptions;
55+
import com.oracle.svm.core.configure.ConditionalRuntimeValue;
56+
import com.oracle.svm.core.configure.RuntimeConditionSet;
5457
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
5558
import com.oracle.svm.core.feature.InternalFeature;
5659
import com.oracle.svm.core.jdk.resources.MissingResourceRegistrationError;
@@ -90,8 +93,8 @@ public static Resources singleton() {
9093
* ends up in the image heap is computed after the runtime module instances have been computed
9194
* {see com.oracle.svm.hosted.ModuleLayerFeature}.
9295
*/
93-
private final EconomicMap<ModuleResourceKey, ResourceStorageEntryBase> resources = ImageHeapMap.create();
94-
private final EconomicMap<RequestedPattern, Boolean> requestedPatterns = ImageHeapMap.create();
96+
private final EconomicMap<ModuleResourceKey, ConditionalRuntimeValue<ResourceStorageEntryBase>> resources = ImageHeapMap.create();
97+
private final EconomicMap<RequestedPattern, RuntimeConditionSet> requestedPatterns = ImageHeapMap.create();
9598

9699
public record RequestedPattern(String module, String resource) {
97100
}
@@ -108,9 +111,9 @@ public record ModuleResourceKey(Module module, String resource) {
108111

109112
/**
110113
* The object used to detect that the resource is not reachable according to the metadata. It
111-
* can be returned by the {@link Resources#get} method if the resource was not correctly
112-
* specified in the configuration, but we do not want to throw directly (for example when we try
113-
* to check all the modules for a resource).
114+
* can be returned by the {@link Resources#getAtRuntime} method if the resource was not
115+
* correctly specified in the configuration, but we do not want to throw directly (for example
116+
* when we try to check all the modules for a resource).
114117
*/
115118
private static final ResourceStorageEntryBase MISSING_METADATA_MARKER = new ResourceStorageEntryBase();
116119

@@ -124,11 +127,11 @@ public record ModuleResourceKey(Module module, String resource) {
124127
Resources() {
125128
}
126129

127-
public EconomicMap<ModuleResourceKey, ResourceStorageEntryBase> getResourceStorage() {
130+
public EconomicMap<ModuleResourceKey, ConditionalRuntimeValue<ResourceStorageEntryBase>> getResourceStorage() {
128131
return resources;
129132
}
130133

131-
public Iterable<ResourceStorageEntryBase> resources() {
134+
public Iterable<ConditionalRuntimeValue<ResourceStorageEntryBase>> resources() {
132135
return resources.getValues();
133136
}
134137

@@ -182,17 +185,18 @@ private void addEntry(Module module, String resourceName, boolean isDirectory, b
182185
Module m = module != null && module.isNamed() ? module : null;
183186
synchronized (resources) {
184187
ModuleResourceKey key = createStorageKey(m, resourceName);
185-
ResourceStorageEntryBase entry = resources.get(key);
188+
RuntimeConditionSet conditionSet = RuntimeConditionSet.emptySet();
189+
ConditionalRuntimeValue<ResourceStorageEntryBase> entry = resources.get(key);
186190
if (isNegativeQuery) {
187191
if (entry == null) {
188-
resources.put(key, NEGATIVE_QUERY_MARKER);
192+
resources.put(key, new ConditionalRuntimeValue<>(conditionSet, NEGATIVE_QUERY_MARKER));
189193
}
190194
return;
191195
}
192196

193-
if (entry == null || entry == NEGATIVE_QUERY_MARKER) {
197+
if (entry == null || entry.getValueUnconditionally() == NEGATIVE_QUERY_MARKER) {
194198
updateTimeStamp();
195-
entry = new ResourceStorageEntry(isDirectory, fromJar);
199+
entry = new ConditionalRuntimeValue<>(conditionSet, new ResourceStorageEntry(isDirectory, fromJar));
196200
resources.put(key, entry);
197201
} else {
198202
if (key.module() != null) {
@@ -201,8 +205,7 @@ private void addEntry(Module module, String resourceName, boolean isDirectory, b
201205
return;
202206
}
203207
}
204-
205-
entry.addData(data);
208+
entry.getValueUnconditionally().addData(data);
206209
}
207210
}
208211

@@ -243,7 +246,7 @@ public void registerIOException(Module module, String resourceName, IOException
243246
ModuleResourceKey key = createStorageKey(module, resourceName);
244247
synchronized (resources) {
245248
updateTimeStamp();
246-
resources.put(key, new ResourceExceptionEntry(e));
249+
resources.put(key, new ConditionalRuntimeValue<>(RuntimeConditionSet.emptySet(), new ResourceExceptionEntry(e)));
247250
}
248251
}
249252

@@ -258,16 +261,11 @@ public void registerNegativeQuery(Module module, String resourceName) {
258261
}
259262

260263
@Platforms(Platform.HOSTED_ONLY.class)
261-
public void registerIncludePattern(String pattern) {
262-
registerIncludePattern(null, pattern);
263-
}
264-
265-
@Platforms(Platform.HOSTED_ONLY.class)
266-
public void registerIncludePattern(String module, String pattern) {
264+
public void registerIncludePattern(ConfigurationCondition condition, String module, String pattern) {
267265
assert MissingRegistrationUtils.throwMissingRegistrationErrors();
268266
synchronized (requestedPatterns) {
269267
updateTimeStamp();
270-
requestedPatterns.put(new RequestedPattern(module, handleEscapedCharacters(pattern)), Boolean.TRUE);
268+
requestedPatterns.put(new RequestedPattern(module, handleEscapedCharacters(pattern)), RuntimeConditionSet.createHosted(condition));
271269
}
272270
}
273271

@@ -310,8 +308,8 @@ private static boolean wasAlreadyInCanonicalForm(String resourceName, String can
310308
return resourceName.equals(canonicalResourceName) || removeTrailingSlash(resourceName).equals(canonicalResourceName);
311309
}
312310

313-
public ResourceStorageEntryBase get(String name, boolean throwOnMissing) {
314-
return get(null, name, throwOnMissing);
311+
public ResourceStorageEntryBase getAtRuntime(String name, boolean throwOnMissing) {
312+
return getAtRuntime(null, name, throwOnMissing);
315313
}
316314

317315
/**
@@ -320,17 +318,18 @@ public ResourceStorageEntryBase get(String name, boolean throwOnMissing) {
320318
* {@link MissingResourceRegistrationError}. This is needed because different modules can be
321319
* tried on the same resource name, causing an unexpected exception if we throw directly.
322320
*/
323-
public ResourceStorageEntryBase get(Module module, String resourceName, boolean throwOnMissing) {
321+
public ResourceStorageEntryBase getAtRuntime(Module module, String resourceName, boolean throwOnMissing) {
324322
String canonicalResourceName = toCanonicalForm(resourceName);
325323
String moduleName = moduleName(module);
326-
ResourceStorageEntryBase entry = resources.get(createStorageKey(module, canonicalResourceName));
324+
ConditionalRuntimeValue<ResourceStorageEntryBase> entry = resources.get(createStorageKey(module, canonicalResourceName));
327325
if (entry == null) {
328326
if (MissingRegistrationUtils.throwMissingRegistrationErrors()) {
329-
MapCursor<RequestedPattern, Boolean> cursor = requestedPatterns.getEntries();
327+
MapCursor<RequestedPattern, RuntimeConditionSet> cursor = requestedPatterns.getEntries();
330328
while (cursor.advance()) {
331329
RequestedPattern moduleResourcePair = cursor.getKey();
332330
if (Objects.equals(moduleName, moduleResourcePair.module) &&
333-
(matchResource(moduleResourcePair.resource, resourceName) || matchResource(moduleResourcePair.resource, canonicalResourceName))) {
331+
((matchResource(moduleResourcePair.resource, resourceName) || matchResource(moduleResourcePair.resource, canonicalResourceName)) &&
332+
cursor.getValue().satisfied())) {
334333
return null;
335334
}
336335
}
@@ -348,27 +347,33 @@ public ResourceStorageEntryBase get(Module module, String resourceName, boolean
348347
return null;
349348
}
350349
}
351-
if (entry.isException()) {
352-
throw new RuntimeException(entry.getException());
350+
if (!entry.getConditions().satisfied()) {
351+
return missingMetadata(resourceName, throwOnMissing);
352+
}
353+
354+
ResourceStorageEntryBase unconditionalEntry = entry.getValue();
355+
assert unconditionalEntry != null : "Already checked above that the condition is satisfied";
356+
if (unconditionalEntry.isException()) {
357+
throw new RuntimeException(unconditionalEntry.getException());
353358
}
354-
if (entry == NEGATIVE_QUERY_MARKER) {
359+
if (unconditionalEntry == NEGATIVE_QUERY_MARKER) {
355360
return null;
356361
}
357-
if (entry.isFromJar() && !wasAlreadyInCanonicalForm(resourceName, canonicalResourceName)) {
362+
if (unconditionalEntry.isFromJar() && !wasAlreadyInCanonicalForm(resourceName, canonicalResourceName)) {
358363
/*
359364
* The resource originally came from a jar file, thus behave like ZipFileSystem behaves
360365
* for non-canonical paths.
361366
*/
362367
return null;
363368
}
364-
if (!entry.isDirectory() && hasTrailingSlash(resourceName)) {
369+
if (!unconditionalEntry.isDirectory() && hasTrailingSlash(resourceName)) {
365370
/*
366371
* If this is an actual resource file (not a directory) we do not tolerate a trailing
367372
* slash.
368373
*/
369374
return null;
370375
}
371-
return entry;
376+
return unconditionalEntry;
372377
}
373378

374379
private static ResourceStorageEntryBase missingMetadata(String resourceName, boolean throwOnMissing) {
@@ -412,15 +417,15 @@ public InputStream createInputStream(Module module, String resourceName) {
412417
return null;
413418
}
414419

415-
ResourceStorageEntryBase entry = get(module, resourceName, false);
420+
ResourceStorageEntryBase entry = getAtRuntime(module, resourceName, false);
416421
boolean isInMetadata = entry != MISSING_METADATA_MARKER;
417422
if (moduleName(module) == null && (entry == MISSING_METADATA_MARKER || entry == null)) {
418423
/*
419424
* If module is not specified or is an unnamed module and entry was not found as
420425
* classpath-resource we have to search for the resource in all modules in the image.
421426
*/
422427
for (Module m : RuntimeModuleSupport.instance().getBootLayer().modules()) {
423-
entry = get(m, resourceName, false);
428+
entry = getAtRuntime(m, resourceName, false);
424429
if (entry != MISSING_METADATA_MARKER) {
425430
isInMetadata = true;
426431
}
@@ -458,15 +463,15 @@ public Enumeration<URL> createURLs(Module module, String resourceName) {
458463
/* If moduleName was unspecified we have to consider all modules in the image */
459464
if (moduleName(module) == null) {
460465
for (Module m : RuntimeModuleSupport.instance().getBootLayer().modules()) {
461-
ResourceStorageEntryBase entry = get(m, resourceName, false);
466+
ResourceStorageEntryBase entry = getAtRuntime(m, resourceName, false);
462467
if (entry == MISSING_METADATA_MARKER) {
463468
continue;
464469
}
465470
missingMetadata = false;
466471
addURLEntries(resourcesURLs, (ResourceStorageEntry) entry, m, shouldAppendTrailingSlash ? canonicalResourceName + '/' : canonicalResourceName);
467472
}
468473
}
469-
ResourceStorageEntryBase explicitEntry = get(module, resourceName, false);
474+
ResourceStorageEntryBase explicitEntry = getAtRuntime(module, resourceName, false);
470475
if (explicitEntry != MISSING_METADATA_MARKER) {
471476
missingMetadata = false;
472477
addURLEntries(resourcesURLs, (ResourceStorageEntry) explicitEntry, module, shouldAppendTrailingSlash ? canonicalResourceName + '/' : canonicalResourceName);
@@ -540,9 +545,10 @@ public void afterCompilation(AfterCompilationAccess access) {
540545
* of lazily initialized fields. Only the byte[] arrays themselves can be safely made
541546
* read-only.
542547
*/
543-
for (ResourceStorageEntryBase entry : Resources.singleton().resources()) {
544-
if (entry.hasData()) {
545-
for (byte[] resource : entry.getData()) {
548+
for (ConditionalRuntimeValue<ResourceStorageEntryBase> entry : Resources.singleton().resources()) {
549+
var unconditionalEntry = entry.getValueUnconditionally();
550+
if (unconditionalEntry.hasData()) {
551+
for (byte[] resource : unconditionalEntry.getData()) {
546552
access.registerAsImmutable(resource);
547553
}
548554
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ public void prepareBundle(String bundleName, ResourceBundle bundle, Function<Str
161161
Optional<Module> module = findModule.apply(bundleNameWithModule[0]);
162162
String finalResourceName = resourceName;
163163
module.ifPresent(m -> ImageSingletons.lookup(RuntimeResourceSupport.class).addResource(m, finalResourceName));
164+
164165
}
165166
}
166167
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/MissingResourceRegistrationUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ private static String errorMessage(String type, String resourcePath) {
6161
ERROR_EMPHASIS_INDENT + resourcePath +
6262
System.lineSeparator() +
6363
System.lineSeparator() +
64-
" without it being registered as reachable. Add it to the resource metadata to solve this problem. " +
64+
"without it being registered as reachable. Add it to the resource metadata to solve this problem. " +
6565
"See https://www.graalvm.org/latest/reference-manual/native-image/metadata/#resources-and-resource-bundles for help";
6666
}
6767

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/resources/NativeImageResourceFileSystem.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
import java.util.concurrent.locks.ReentrantReadWriteLock;
8585
import java.util.regex.Pattern;
8686

87+
import com.oracle.svm.core.configure.ConditionalRuntimeValue;
8788
import org.graalvm.collections.MapCursor;
8889

8990
import com.oracle.svm.core.MissingRegistrationUtils;
@@ -575,7 +576,7 @@ IndexNode getInode(byte[] path) {
575576
IndexNode indexNode = inodes.get(IndexNode.keyOf(path));
576577
if (indexNode == null && MissingRegistrationUtils.throwMissingRegistrationErrors()) {
577578
// Try to access the resource to see if the metadata is present
578-
Resources.singleton().get(getString(path), true);
579+
Resources.singleton().getAtRuntime(getString(path), true);
579580
}
580581
return indexNode;
581582
}
@@ -656,11 +657,11 @@ private void update(Entry e) {
656657
}
657658

658659
private void readAllEntries() {
659-
MapCursor<Resources.ModuleResourceKey, ResourceStorageEntryBase> entries = Resources.singleton().getResourceStorage().getEntries();
660+
MapCursor<Resources.ModuleResourceKey, ConditionalRuntimeValue<ResourceStorageEntryBase>> entries = Resources.singleton().getResourceStorage().getEntries();
660661
while (entries.advance()) {
661662
byte[] name = getBytes(entries.getKey().resource());
662-
ResourceStorageEntryBase entry = entries.getValue();
663-
if (entry.hasData()) {
663+
ResourceStorageEntryBase entry = entries.getValue().getValue();
664+
if (entry != null && entry.hasData()) {
664665
IndexNode newIndexNode = new IndexNode(name, entry.isDirectory(), true);
665666
inodes.put(newIndexNode, newIndexNode);
666667
}

0 commit comments

Comments
 (0)