Skip to content

Commit 5ac3938

Browse files
committed
[GR-40906] Add RuntimeResourceAccess#addResource(Module, String, byte[]) API method.
PullRequest: graal/12641
2 parents 4b235a5 + 5d7f468 commit 5ac3938

File tree

9 files changed

+63
-14
lines changed

9 files changed

+63
-14
lines changed

sdk/src/org.graalvm.nativeimage/snapshot.sigtest

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,7 @@ supr java.lang.Object
10171017

10181018
CLSS public final org.graalvm.nativeimage.hosted.RuntimeResourceAccess
10191019
meth public static void addResource(java.lang.Module,java.lang.String)
1020+
meth public static void addResource(java.lang.Module,java.lang.String,byte[])
10201021
meth public static void addResourceBundle(java.lang.Module,java.lang.String,java.util.Locale[])
10211022
meth public static void addResourceBundle(java.lang.Module,java.lang.String)
10221023
supr java.lang.Object

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,28 @@ public final class RuntimeResourceAccess {
6767
* @since 22.3
6868
*/
6969
public static void addResource(Module module, String resourcePath) {
70+
Objects.requireNonNull(module);
71+
Objects.requireNonNull(resourcePath);
7072
ImageSingletons.lookup(RuntimeResourceSupport.class).addResources(ConfigurationCondition.alwaysTrue(),
7173
withModuleName(module, Pattern.quote(resourcePath)));
7274
}
7375

76+
/**
77+
* Inject a Java resource at {@code resourcePath} in {@code module} with the specified
78+
* {@code resourceContent}. At runtime the resource can be accessed as if it was part of the
79+
* original application. If the given {@code module} is unnamed, the resource is placed on the
80+
* classpath instead.
81+
*
82+
* @since 22.3
83+
*/
84+
public static void addResource(Module module, String resourcePath, byte[] resourceContent) {
85+
Objects.requireNonNull(module);
86+
Objects.requireNonNull(resourcePath);
87+
Objects.requireNonNull(resourceContent);
88+
ImageSingletons.lookup(RuntimeResourceSupport.class).injectResource(
89+
module, resourcePath, resourceContent);
90+
}
91+
7492
/**
7593
* Make Java ResourceBundle that is specified by a {@code baseBundleName} and {@code locales}
7694
* from module {@code module} available at run time. If the given {@code module} is unnamed, the

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
public interface RuntimeResourceSupport {
4747
void addResources(ConfigurationCondition condition, String pattern);
4848

49+
void injectResource(Module module, String resourcePath, byte[] resourceContent);
50+
4951
void ignoreResources(ConfigurationCondition condition, String pattern);
5052

5153
void addResourceBundles(ConfigurationCondition condition, String name);

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This changelog summarizes major changes to GraalVM Native Image.
1313
* (GR-15630) Allow multiple classes with the same name from different class loaders.
1414
* (GR-40198) Introduce public API for programmatic JNI / Resource / Proxy / Serialization registration from Feature classes during the image build.
1515
* (GR-38909) Moved strictly-internal annotation classes (e.g. @AlwaysInline, @NeverInline, @Uninterruptible, ...) out of com.oracle.svm.core.annotate. Moved remaining annotation classes to org.graalvm.sdk module.
16+
* (GR-40906) Add RuntimeResourceAccess#addResource(Module module, String resourcePath, byte[] resource) API method that allows injecting resources into images
1617

1718
## Version 22.2.0
1819
* (GR-20653) Re-enable the usage of all CPU features for JIT compilation on AMD64.

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ public void addResources(ConfigurationCondition condition, String pattern) {
9393
addedResources.add(pattern);
9494
}
9595

96+
@Override
97+
public void injectResource(Module module, String resourcePath, byte[] resourceContent) {
98+
}
99+
96100
@Override
97101
public void ignoreResources(ConfigurationCondition condition, String pattern) {
98102
ignoredResources.add(pattern);

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,16 @@
3535
import java.util.concurrent.ConcurrentMap;
3636
import java.util.regex.Pattern;
3737

38-
import com.oracle.svm.core.configure.ConfigurationParser;
39-
import com.oracle.svm.core.configure.ResourceConfigurationParser;
4038
import org.graalvm.nativeimage.impl.ConfigurationCondition;
4139

4240
import com.oracle.svm.configure.ConfigurationBase;
4341
import com.oracle.svm.configure.json.JsonPrinter;
4442
import com.oracle.svm.configure.json.JsonWriter;
4543
import com.oracle.svm.core.configure.ConditionalElement;
44+
import com.oracle.svm.core.configure.ConfigurationParser;
45+
import com.oracle.svm.core.configure.ResourceConfigurationParser;
4646
import com.oracle.svm.core.configure.ResourcesRegistry;
47+
import com.oracle.svm.core.util.VMError;
4748

4849
public final class ResourceConfiguration extends ConfigurationBase<ResourceConfiguration, ResourceConfiguration.Predicate> {
4950

@@ -62,6 +63,11 @@ public void addResources(ConfigurationCondition condition, String pattern) {
6263
configuration.addResourcePattern(condition, pattern);
6364
}
6465

66+
@Override
67+
public void injectResource(Module module, String resourcePath, byte[] resourceContent) {
68+
VMError.shouldNotReachHere("Resource injection is only supported via Feature implementation");
69+
}
70+
6571
@Override
6672
public void ignoreResources(ConfigurationCondition condition, String pattern) {
6773
configuration.ignoreResourcePattern(condition, pattern);

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,16 @@ public static byte[] inputStreamToByteArray(InputStream is) {
8686
}
8787

8888
private static void addEntry(String moduleName, String resourceName, boolean isDirectory, byte[] data, boolean fromJar) {
89-
Resources support = singleton();
90-
Pair<String, String> key = Pair.create(moduleName, resourceName);
91-
ResourceStorageEntry entry = support.resources.get(key);
92-
if (entry == null) {
93-
entry = new ResourceStorageEntry(isDirectory, fromJar);
94-
support.resources.put(key, entry);
89+
var resources = singleton().resources;
90+
synchronized (resources) {
91+
Pair<String, String> key = Pair.create(moduleName, resourceName);
92+
ResourceStorageEntry entry = resources.get(key);
93+
if (entry == null) {
94+
entry = new ResourceStorageEntry(isDirectory, fromJar);
95+
resources.put(key, entry);
96+
}
97+
entry.getData().add(data);
9598
}
96-
entry.getData().add(data);
9799
}
98100

99101
@Platforms(Platform.HOSTED_ONLY.class)
@@ -111,6 +113,11 @@ public static void registerResource(String moduleName, String resourceName, Inpu
111113
registerResource(moduleName, resourceName, is, true);
112114
}
113115

116+
@Platforms(Platform.HOSTED_ONLY.class)
117+
public static void registerResource(String moduleName, String resourceName, byte[] resourceContent) {
118+
addEntry(moduleName, resourceName, false, resourceContent, true);
119+
}
120+
114121
@Platforms(Platform.HOSTED_ONLY.class)
115122
public static void registerResource(String moduleName, String resourceName, InputStream is, boolean fromJar) {
116123
addEntry(moduleName, resourceName, false, inputStreamToByteArray(is), fromJar);

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ void processClassLoaderOptions() {
403403

404404
private static void processListModulesOption(ModuleLayer layer) {
405405
Class<?> launcherHelperClass = ReflectionUtil.lookupClass(false, "sun.launcher.LauncherHelper");
406+
Method initOutputMethod = ReflectionUtil.lookupMethod(launcherHelperClass, "initOutput", boolean.class);
406407
Method showModuleMethod = ReflectionUtil.lookupMethod(launcherHelperClass, "showModule", ModuleReference.class);
407408

408409
boolean first = true;
@@ -411,6 +412,11 @@ private static void processListModulesOption(ModuleLayer layer) {
411412
.sorted(Comparator.comparing(ResolvedModule::name))
412413
.collect(Collectors.toList());
413414
if (first) {
415+
try {
416+
initOutputMethod.invoke(null, false);
417+
} catch (ReflectiveOperationException e) {
418+
throw VMError.shouldNotReachHere("Unable to use " + initOutputMethod + " to set printing with " + showModuleMethod + " to System.out.", e);
419+
}
414420
first = false;
415421
} else if (!resolvedModules.isEmpty()) {
416422
System.out.println();
@@ -419,7 +425,7 @@ private static void processListModulesOption(ModuleLayer layer) {
419425
try {
420426
showModuleMethod.invoke(null, resolvedModule.reference());
421427
} catch (ReflectiveOperationException e) {
422-
throw VMError.shouldNotReachHere("Unable to " + showModuleMethod + " for printing list of modules.", e);
428+
throw VMError.shouldNotReachHere("Unable to use " + showModuleMethod + " for printing list of modules.", e);
423429
}
424430
}
425431
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import com.oracle.svm.core.configure.ConfigurationFiles;
5353
import com.oracle.svm.core.configure.ResourceConfigurationParser;
5454
import com.oracle.svm.core.configure.ResourcesRegistry;
55+
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
5556
import com.oracle.svm.core.feature.InternalFeature;
5657
import com.oracle.svm.core.jdk.Resources;
5758
import com.oracle.svm.core.jdk.resources.NativeImageResourceFileAttributes;
@@ -60,7 +61,6 @@
6061
import com.oracle.svm.core.jdk.resources.NativeImageResourceFileSystemProvider;
6162
import com.oracle.svm.core.option.HostedOptionKey;
6263
import com.oracle.svm.core.option.LocatableMultiOptionValue;
63-
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
6464
import com.oracle.svm.core.util.UserError;
6565
import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl;
6666
import com.oracle.svm.hosted.config.ConfigurationParserUtils;
@@ -133,6 +133,12 @@ public void addResources(ConfigurationCondition condition, String pattern) {
133133
});
134134
}
135135

136+
@Override
137+
public void injectResource(Module module, String resourcePath, byte[] resourceContent) {
138+
var moduleName = module.isNamed() ? module.getName() : null;
139+
Resources.registerResource(moduleName, resourcePath, resourceContent);
140+
}
141+
136142
@Override
137143
public void ignoreResources(ConfigurationCondition condition, String pattern) {
138144
if (configurationTypeResolver.resolveType(condition.getTypeName()) == null) {
@@ -261,13 +267,11 @@ public void duringAnalysis(DuringAnalysisAccess access) {
261267

262268
access.requireAnalysisIteration();
263269

264-
DebugContext debugContext = ((DuringAnalysisAccessImpl) access).getDebugContext();
265270
ResourcePattern[] includePatterns = compilePatterns(resourcePatternWorkSet);
266271
ResourcePattern[] excludePatterns = compilePatterns(excludedResourcePatterns);
272+
DebugContext debugContext = ((DuringAnalysisAccessImpl) access).getDebugContext();
267273
ResourceCollectorImpl collector = new ResourceCollectorImpl(debugContext, includePatterns, excludePatterns, includedResourcesModules);
268-
269274
ImageSingletons.lookup(ClassLoaderSupport.class).collectResources(collector);
270-
271275
resourcePatternWorkSet.clear();
272276
}
273277

0 commit comments

Comments
 (0)