Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
a180a4b
Move resource registration to beforeAnalysis phase
dnestoro May 11, 2023
252861c
Try to speed resource traversing by introducing parallelism
dnestoro May 11, 2023
ee5f501
Change function that public API uses to register resource
dnestoro May 16, 2023
f3e5980
Add resource registration through API without patterns
dnestoro May 19, 2023
7865a6c
Try to open modules and decide whether resource comes from jar
dnestoro May 19, 2023
705835d
Replace CharsetSubstitution resource adding
dnestoro May 25, 2023
eaafc3d
Change addResource function to check whether the entry is directory o…
dnestoro May 29, 2023
82fdd40
Extract resource adding from beforeAnalysis to duringSetup in Truffle…
dnestoro May 29, 2023
5e71750
Extract bunndles registration from pattern based addResources
dnestoro May 30, 2023
1468ef1
Replace resource Bundles registration with non-pattern-based implemen…
dnestoro May 31, 2023
55c9af1
Add null pointer check for module classLoader
dnestoro May 31, 2023
5d53612
Add .properties extension to resourceBundle name
dnestoro Jun 1, 2023
5633755
Add module lookup map
dnestoro Jun 8, 2023
fa166d8
Add unnamed module case
dnestoro Jun 9, 2023
2b762d9
Move resource adding to duringSetup when the RuntimeResourceSupport i…
dnestoro Jun 16, 2023
b4ca2f2
Try to match resource pattern
dnestoro Jun 16, 2023
8a7f024
Cover the case when resource has condition
dnestoro Jun 20, 2023
7a34bb3
Add conditional resource directory registration test
dnestoro Jul 5, 2023
8b02c19
Refactor adding content to directory resource
dnestoro Jul 12, 2023
f2a4fbc
Replace pairs with records to get more semantic
dnestoro Jul 18, 2023
f49fe93
Get content for directories inside jar
dnestoro Jul 19, 2023
a5ca553
Add possiblity to register resource for various conditions
dnestoro Jul 28, 2023
1f28251
Prevent registration of same resources multiple times
dnestoro Aug 1, 2023
130eb2a
Resolve conflicts
dnestoro Aug 11, 2023
18a1797
Remove exceptions that could not be thrown from method signature
dnestoro Aug 16, 2023
08167ef
Remove unused import from mx file
dnestoro Aug 16, 2023
12aa181
Revert locale argument for prepareBundle function
dnestoro Aug 18, 2023
de5d307
Add missing throw when using VMError
dnestoro Aug 22, 2023
fb8105d
Replace findModule with Class.class.getModule for java.base scenario
dnestoro Aug 22, 2023
69646bc
Remove comments from prepareBundle
dnestoro Aug 22, 2023
9c59901
Add null check guard for findModule
dnestoro Aug 22, 2023
03854b2
Remove redudant functions and improve duplicates checking
dnestoro Oct 2, 2023
9b9ed1f
Register negative query directories
dnestoro Oct 6, 2023
167a727
Fix package export from module
dnestoro Oct 9, 2023
620f813
Remove redudant parameters from resource registration functions
dnestoro Oct 10, 2023
2e76995
Remove sufficient prints
dnestoro Oct 10, 2023
1635c2b
Cover case when same resource name can occur in multiple bundles
dnestoro Oct 11, 2023
52d9e72
Restructure code for better readability
dnestoro Oct 11, 2023
0f90072
Add synchronization for alreadyAddedResources check
dnestoro Oct 11, 2023
17f84cc
Cleanup code
dnestoro Oct 11, 2023
45c27ed
Convert ResorucePattern class to record
dnestoro Oct 12, 2023
30e5c86
Remove debugg context since it is not used anymore
dnestoro Oct 12, 2023
c898d38
Add explanation for shouldRegisterResource function
dnestoro Oct 12, 2023
0853a1c
Add function that is never used just to pass gates
dnestoro Oct 13, 2023
56bdd98
Replace module export with module open access
dnestoro Oct 17, 2023
e1807e0
Update imports according to changes on master
dnestoro Oct 20, 2023
ec0913f
Inline function and remove passing null for findModule function
dnestoro Oct 24, 2023
9de65c8
Avoid using synchronized block all the time
dnestoro Oct 24, 2023
2da282f
Replace multiple calls of string transformation with function
dnestoro Oct 24, 2023
4b9c4d7
Extract directory registration handling form registerResoruce function
dnestoro Oct 24, 2023
f54f22c
Rebase and fix imports
dnestoro Oct 24, 2023
9f793ce
Rename includeAll variable to includeCurrent
dnestoro Oct 24, 2023
e006dd4
Use Resources#registerIOException instead of ignoring exception
dnestoro Oct 25, 2023
b552181
Revert overridden prepareBundle function because it can be called fro…
dnestoro Oct 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -40,17 +40,16 @@
*/
package org.graalvm.nativeimage.hosted;

import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Pattern;

import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.impl.ConfigurationCondition;
import org.graalvm.nativeimage.impl.RuntimeResourceSupport;

import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;

/**
* This class can be used to register Java resources and ResourceBundles that should be accessible
* at run time.
Expand All @@ -69,8 +68,7 @@ public final class RuntimeResourceAccess {
public static void addResource(Module module, String resourcePath) {
Objects.requireNonNull(module);
Objects.requireNonNull(resourcePath);
ImageSingletons.lookup(RuntimeResourceSupport.class).addResources(ConfigurationCondition.alwaysTrue(),
withModuleName(module, Pattern.quote(resourcePath)));
ImageSingletons.lookup(RuntimeResourceSupport.class).addResource(module, resourcePath);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -50,6 +50,10 @@ public static ConfigurationCondition alwaysTrue() {
return OBJECT_REACHABLE;
}

public static boolean isAlwaysTrue(ConfigurationCondition condition) {
return ConfigurationCondition.alwaysTrue().equals(condition);
}

public static ConfigurationCondition create(String typeReachability) {
Objects.requireNonNull(typeReachability);
if (OBJECT_REACHABLE.typeName.equals(typeReachability)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
Expand Down Expand Up @@ -46,6 +46,8 @@
public interface RuntimeResourceSupport {
void addResources(ConfigurationCondition condition, String pattern);

void addResource(Module module, String resourcePath);

void injectResource(Module module, String resourcePath, byte[] resourceContent);

void ignoreResources(ConfigurationCondition condition, String pattern);
Expand Down
18 changes: 18 additions & 0 deletions substratevm/mx.substratevm/mx_substratevm.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import tempfile
from glob import glob
from contextlib import contextmanager
from distutils.dir_util import mkpath # pylint: disable=no-name-in-module
from os.path import join, exists, dirname
import pipes
from argparse import ArgumentParser
Expand Down Expand Up @@ -475,9 +476,26 @@ def native_unittests_task(extra_build_args=None):
# GR-24075
mx_unittest.add_global_ignore_glob('com.oracle.svm.test.ProcessPropertiesTest')

# add resources that are not in jar but in the separate directory
cp_entry_name = join(svmbuild_dir(), 'cpEntryDir')
resources_from_dir = join(cp_entry_name, 'resourcesFromDir')
simple_dir = join(cp_entry_name, 'simpleDir')

mkpath(cp_entry_name)
mkpath(resources_from_dir)
mkpath(simple_dir)

for i in range(4):
with open(join(cp_entry_name, "resourcesFromDir", f'cond-resource{i}.txt'), 'w') as out:
out.write(f"Conditional file{i}" + '\n')

with open(join(cp_entry_name, "simpleDir", f'simple-resource{i}.txt'), 'w') as out:
out.write(f"Simple file{i}" + '\n')

additional_build_args = svm_experimental_options([
'-H:AdditionalSecurityProviders=com.oracle.svm.test.SecurityServiceTest$NoOpProvider',
'-H:AdditionalSecurityServiceTypes=com.oracle.svm.test.SecurityServiceTest$JCACompliantNoOpService',
'-cp', cp_entry_name
])
if extra_build_args is not None:
additional_build_args += extra_build_args
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@
import org.junit.Test;

import com.oracle.svm.configure.config.ResourceConfiguration;
import com.oracle.svm.core.util.json.JsonWriter;
import com.oracle.svm.core.configure.ResourceConfigurationParser;
import com.oracle.svm.core.configure.ResourcesRegistry;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.core.util.json.JsonWriter;

public class ResourceConfigurationTest {

Expand Down Expand Up @@ -93,6 +94,11 @@ public void addResources(ConfigurationCondition condition, String pattern) {
addedResources.add(pattern);
}

@Override
public void addResource(Module module, String resourcePath) {
throw VMError.shouldNotReachHere("Unused function.");
}

@Override
public void injectResource(Module module, String resourcePath, byte[] resourceContent) {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@
import org.graalvm.nativeimage.impl.ConfigurationCondition;

import com.oracle.svm.configure.ConfigurationBase;
import com.oracle.svm.core.util.json.JsonPrinter;
import com.oracle.svm.core.util.json.JsonWriter;
import com.oracle.svm.core.configure.ConditionalElement;
import com.oracle.svm.core.configure.ConfigurationParser;
import com.oracle.svm.core.configure.ResourceConfigurationParser;
import com.oracle.svm.core.configure.ResourcesRegistry;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.core.util.json.JsonPrinter;
import com.oracle.svm.core.util.json.JsonWriter;

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

Expand All @@ -63,6 +63,11 @@ public void addResources(ConfigurationCondition condition, String pattern) {
configuration.addResourcePattern(condition, pattern);
}

@Override
public void addResource(Module module, String resourcePath) {
throw VMError.shouldNotReachHere("Unused function.");
}

@Override
public void injectResource(Module module, String resourcePath, byte[] resourceContent) {
VMError.shouldNotReachHere("Resource injection is only supported via Feature implementation");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@
package com.oracle.svm.core;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.impl.ConfigurationCondition;

@Platforms(Platform.HOSTED_ONLY.class)
public abstract class ClassLoaderSupport {
Expand All @@ -51,12 +53,11 @@ public boolean isNativeImageClassLoader(ClassLoader classLoader) {
protected abstract boolean isNativeImageClassLoaderImpl(ClassLoader classLoader);

public interface ResourceCollector {
List<ConfigurationCondition> isIncluded(Module module, String resourceName, URI resourceURI);

boolean isIncluded(Module module, String resourceName, URI resourceURI);
void addResource(Module module, String resourceName);

void addResource(Module module, String resourceName, InputStream resourceStream, boolean fromJar);

void addDirectoryResource(Module module, String dir, String content, boolean fromJar);
void addResourceConditionally(Module module, String resourceName, ConfigurationCondition condition);

void registerNegativeQuery(Module module, String resourceName);

Expand All @@ -66,4 +67,6 @@ public interface ResourceCollector {
public abstract void collectResources(ResourceCollector resourceCollector);

public abstract List<ResourceBundle> getResourceBundle(String bundleName, Locale locale);

public abstract Map<String, Set<Module>> getPackageToModules();
}
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ private void updateTimeStamp() {
}

@Platforms(Platform.HOSTED_ONLY.class)
private ResourceStorageEntryBase addEntry(Module module, String resourceName, ResourceStorageEntryBase newEntry, boolean isDirectory, boolean fromJar) {
private void addEntry(Module module, String resourceName, boolean isDirectory, byte[] data, boolean fromJar, boolean isNegativeQuery) {
VMError.guarantee(!BuildPhaseProvider.isAnalysisFinished(), "Trying to add a resource entry after analysis.");
Module m = module != null && module.isNamed() ? module : null;
if (m != null) {
Expand All @@ -175,58 +175,42 @@ private ResourceStorageEntryBase addEntry(Module module, String resourceName, Re
synchronized (resources) {
Pair<Module, String> key = createStorageKey(m, resourceName);
ResourceStorageEntryBase entry = resources.get(key);
if (isNegativeQuery) {
if (entry == null) {
resources.put(key, NEGATIVE_QUERY_MARKER);
}
return;
}

if (entry == null || entry == NEGATIVE_QUERY_MARKER) {
entry = newEntry == null ? new ResourceStorageEntry(isDirectory, fromJar) : newEntry;
updateTimeStamp();
entry = new ResourceStorageEntry(isDirectory, fromJar);
resources.put(key, entry);
} else {
if (key.getLeft() != null) {
// if the entry already exists, and it comes from a module, it is the same entry
// that we registered at some point before
return;
}
}
return entry;
}
}

private void addEntry(Module module, String resourceName, boolean isDirectory, byte[] data, boolean fromJar) {
ResourceStorageEntryBase entry = addEntry(module, resourceName, null, isDirectory, fromJar);
entry.getData().add(data);
entry.getData().add(data);
}
}

@Platforms(Platform.HOSTED_ONLY.class)
public static void registerResource(String resourceName, InputStream is) {
singleton().registerResource(null, resourceName, is, true);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void registerResource(String resourceName, InputStream is, boolean fromJar) {
registerResource(null, resourceName, is, fromJar);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void registerResource(Module module, String resourceName, InputStream is) {
registerResource(module, resourceName, is, true);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void registerResource(Module module, String resourceName, byte[] resourceContent) {
addEntry(module, resourceName, false, resourceContent, true);
addEntry(module, resourceName, false, resourceContent, true, false);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void registerResource(Module module, String resourceName, InputStream is, boolean fromJar) {
addEntry(module, resourceName, false, inputStreamToByteArray(is), fromJar);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void registerDirectoryResource(String resourceDirName, String content) {
registerDirectoryResource(null, resourceDirName, content, true);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void registerDirectoryResource(String resourceDirName, String content, boolean fromJar) {
registerDirectoryResource(null, resourceDirName, content, fromJar);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void registerDirectoryResource(Module module, String resourceDirName, String content) {
registerDirectoryResource(module, resourceDirName, content, true);
addEntry(module, resourceName, false, inputStreamToByteArray(is), fromJar, false);
}

@Platforms(Platform.HOSTED_ONLY.class)
Expand All @@ -236,21 +220,16 @@ public void registerDirectoryResource(Module module, String resourceDirName, Str
* 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.
*/
addEntry(module, resourceDirName, true, content.getBytes(), fromJar);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void registerIOException(String resourceName, IOException e, boolean linkAtBuildTime) {
registerIOException(null, resourceName, e, linkAtBuildTime);
addEntry(module, resourceDirName, true, content.getBytes(), fromJar, false);
}

@Platforms(Platform.HOSTED_ONLY.class)
public void registerIOException(Module module, String resourceName, IOException e, boolean linkAtBuildTime) {
if (linkAtBuildTime) {
if (SubstrateOptions.ThrowLinkAtBuildTimeIOExceptions.getValue()) {
throw new RuntimeException("Resource " + resourceName + " from module " + module.getName() + " produced an IOException.", e);
throw new RuntimeException("Resource " + resourceName + " from module " + moduleName(module) + " produced an IOException.", e);
} else {
LogUtils.warning("Resource " + resourceName + " from module " + module.getName() + " produced the following IOException: " + e.getClass().getTypeName() + ": " + e.getMessage());
LogUtils.warning("Resource " + resourceName + " from module " + moduleName(module) + " produced the following IOException: " + e.getClass().getTypeName() + ": " + e.getMessage());
}
}
Pair<Module, String> key = createStorageKey(module, resourceName);
Expand All @@ -267,7 +246,7 @@ public void registerNegativeQuery(String resourceName) {

@Platforms(Platform.HOSTED_ONLY.class)
public void registerNegativeQuery(Module module, String resourceName) {
addEntry(module, resourceName, NEGATIVE_QUERY_MARKER, false, false);
addEntry(module, resourceName, false, null, false, true);
}

@Platforms(Platform.HOSTED_ONLY.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@
import java.util.ListResourceBundle;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ForkJoinPool;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import jdk.graal.compiler.debug.GraalError;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

Expand All @@ -49,6 +50,7 @@
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.debug.GraalError;
import sun.util.resources.OpenListResourceBundle;
import sun.util.resources.ParallelListResourceBundle;

Expand Down Expand Up @@ -172,8 +174,8 @@ public boolean isNotIncluded(String bundleName) {
}

@Override
public void prepareBundle(String bundleName, ResourceBundle bundle, Locale locale) {
super.prepareBundle(bundleName, bundle, locale);
public void prepareBundle(String bundleName, ResourceBundle bundle, Function<String, Optional<Module>> findModule, Locale locale) {
super.prepareBundle(bundleName, bundle, findModule, locale);
/* Initialize ResourceBundle.keySet eagerly */
bundle.keySet();
this.existingBundles.add(control.toBundleName(bundleName, locale));
Expand Down
Loading