Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, 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 @@ -56,7 +56,7 @@ static RuntimeResourceSupport<ConfigurationCondition> singleton() {

void addGlob(C condition, String module, String glob, Object origin);

void ignoreResources(C condition, String pattern);
void ignoreResources(C condition, String pattern, Object origin);

void addResourceBundles(C condition, String name);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -113,7 +113,7 @@ public void injectResource(Module module, String resourcePath, byte[] resourceCo
}

@Override
public void ignoreResources(UnresolvedConfigurationCondition condition, String pattern) {
public void ignoreResources(UnresolvedConfigurationCondition condition, String pattern, Object origin) {
ignoredResources.add(pattern);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -95,7 +95,7 @@ private void parseResourcesObject(Object resourcesObject, Object origin) {
if (excludesObject != null) {
List<Object> excludes = asList(excludesObject, "Attribute 'excludes' must be a list of resources");
for (Object object : excludes) {
parsePatternEntry(object, registry::ignoreResources, null, "'excludes' list");
parsePatternEntry(object, (condition, pattern) -> registry.ignoreResources(condition, pattern, origin), null, "'excludes' list");
}
}
} else { // Old format: may be deprecated in future versions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -51,7 +51,7 @@ default void addResources(C condition, String pattern) {
}

@Override
void ignoreResources(C condition, String pattern);
void ignoreResources(C condition, String pattern, Object origin);

@Override
void addResourceBundles(C condition, String name);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -94,7 +94,7 @@ public void injectResource(Module module, String resourcePath, byte[] resourceCo
}

@Override
public void ignoreResources(UnresolvedConfigurationCondition condition, String pattern) {
public void ignoreResources(UnresolvedConfigurationCondition condition, String pattern, Object origin) {
configuration.ignoreResourcePattern(condition, pattern);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -38,8 +38,9 @@
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

import com.oracle.svm.core.util.UserError;
import com.oracle.svm.core.ClassLoaderSupport;
import com.oracle.svm.util.GlobUtils;
import com.oracle.svm.util.LogUtils;
import com.oracle.svm.util.StringUtil;

/**
Expand Down Expand Up @@ -105,12 +106,9 @@ public static <C> GlobTrieNode<C> build(List<GlobWithInfo<C>> patterns) {
List<GlobWithInfo<C>> starPatterns = new ArrayList<>();
List<GlobWithInfo<C>> noStarPatterns = new ArrayList<>();

List<String> invalidPatterns = classifyPatterns(patterns, doubleStarPatterns, starPatterns, noStarPatterns);
if (!invalidPatterns.isEmpty()) {
StringBuilder sb = new StringBuilder("Error: invalid glob patterns found:" + System.lineSeparator());
invalidPatterns.forEach(msg -> sb.append(msg).append(System.lineSeparator()));

throw UserError.abort(sb.toString());
List<String> invalidPatternsErrors = classifyPatterns(patterns, doubleStarPatterns, starPatterns, noStarPatterns);
if (!invalidPatternsErrors.isEmpty()) {
invalidPatternsErrors.forEach(LogUtils::warning);
}

/* sort patterns in the groups based on generality */
Expand Down Expand Up @@ -221,7 +219,12 @@ private static <C> List<String> classifyPatterns(List<GlobWithInfo<C>> patterns,
/* validate patterns */
String error = GlobUtils.validatePattern(patternWithInfo.pattern());
if (!error.isEmpty()) {
invalidPatterns.add(error);
if (patternWithInfo.additionalContent() instanceof ClassLoaderSupport.ConditionWithOrigin conditionWithOrigin) {
invalidPatterns.add(error + "Pattern is from: " + conditionWithOrigin.origin());
} else {
invalidPatterns.add(error);
}

continue;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -53,6 +53,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors;

import org.graalvm.nativeimage.ImageSingletons;
Expand Down Expand Up @@ -169,7 +170,7 @@ private record CompiledConditionalPattern(ConfigurationCondition condition, Reso

private Set<ConditionalPattern> resourcePatternWorkSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
private Set<ConditionalPattern> globWorkSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
private final Set<String> excludedResourcePatterns = Collections.newSetFromMap(new ConcurrentHashMap<>());
private final Set<ConditionalPattern> excludedResourcePatterns = Collections.newSetFromMap(new ConcurrentHashMap<>());

private int loadedConfigurations;
private ImageClassLoader imageClassLoader;
Expand Down Expand Up @@ -233,11 +234,11 @@ public void injectResource(Module module, String resourcePath, byte[] resourceCo
}

@Override
public void ignoreResources(ConfigurationCondition condition, String pattern) {
public void ignoreResources(ConfigurationCondition condition, String pattern, Object origin) {
registerConditionalConfiguration(condition, (cnd) -> {
UserError.guarantee(!sealed, "Resources ignored too late: %s", pattern);

excludedResourcePatterns.add(pattern);
excludedResourcePatterns.add(new ConditionalPattern(condition, pattern, origin));
});
}

Expand Down Expand Up @@ -442,17 +443,11 @@ public void beforeAnalysis(BeforeAnalysisAccess a) {
}

/* prepare regex patterns for resource registration */
resourcePatternWorkSet.addAll(Options.IncludeResources.getValue()
.getValuesWithOrigins()
.map(e -> new ConditionalPattern(ConfigurationCondition.alwaysTrue(), e.value(), e.origin()))
.toList());
Set<CompiledConditionalPattern> includePatterns = resourcePatternWorkSet
.stream()
.map(e -> new CompiledConditionalPattern(e.condition(), makeResourcePattern(e.pattern()), e.origin()))
.collect(Collectors.toSet());
resourcePatternWorkSet.addAll(getPatternsFromOption(Options.IncludeResources.getValue()));
Set<CompiledConditionalPattern> includePatterns = compilePatternWorkset(resourcePatternWorkSet);

excludedResourcePatterns.addAll(Options.ExcludeResources.getValue().values());
ResourcePattern[] excludePatterns = compilePatterns(excludedResourcePatterns);
excludedResourcePatterns.addAll(getPatternsFromOption(Options.ExcludeResources.getValue()));
Set<CompiledConditionalPattern> excludePatterns = compilePatternWorkset(excludedResourcePatterns);

ResourceCollectorImpl collector = new ResourceCollectorImpl(includePatterns, excludePatterns);
/*
Expand Down Expand Up @@ -488,7 +483,7 @@ public void beforeAnalysis(BeforeAnalysisAccess a) {

private static final class ResourceCollectorImpl extends ConditionalConfigurationRegistry implements ResourceCollector {
private final Set<CompiledConditionalPattern> includePatterns;
private final ResourcePattern[] excludePatterns;
private final Set<CompiledConditionalPattern> excludePatterns;
private static final int WATCHDOG_RESET_AFTER_EVERY_N_RESOURCES = 1000;
private static final int WATCHDOG_INITIAL_WARNING_AFTER_N_SECONDS = 60;
private static final int WATCHDOG_WARNING_AFTER_EVERY_N_SECONDS = 20;
Expand All @@ -497,7 +492,7 @@ private static final class ResourceCollectorImpl extends ConditionalConfiguratio
private volatile String currentlyProcessedEntry;
ScheduledExecutorService scheduledExecutor;

private ResourceCollectorImpl(Set<CompiledConditionalPattern> includePatterns, ResourcePattern[] excludePatterns) {
private ResourceCollectorImpl(Set<CompiledConditionalPattern> includePatterns, Set<CompiledConditionalPattern> excludePatterns) {
this.includePatterns = includePatterns;
this.excludePatterns = excludePatterns;

Expand Down Expand Up @@ -542,11 +537,11 @@ public List<ConditionWithOrigin> isIncluded(Module module, String resourceName,
* Once migration to glob patterns is done, this code should be removed (include and
* exclude patterns)
*/
for (ResourcePattern rp : excludePatterns) {
if (!rp.moduleNameMatches(moduleName)) {
for (CompiledConditionalPattern rp : excludePatterns) {
if (!rp.compiledPattern.moduleNameMatches(moduleName)) {
continue;
}
if (rp.pattern.matcher(resourceName).matches()) {
if (rp.compiledPattern().pattern.matcher(resourceName).matches()) {
return List.of(); // nothing should match excluded resource
}
}
Expand Down Expand Up @@ -606,21 +601,34 @@ public void registerIncludePattern(ConfigurationCondition condition, String modu
}
}

private ResourcePattern[] compilePatterns(Set<String> patterns) {
private static List<ConditionalPattern> getPatternsFromOption(AccumulatingLocatableMultiOptionValue.Strings option) {
return option
.getValuesWithOrigins()
.map(e -> new ConditionalPattern(ConfigurationCondition.alwaysTrue(), e.value(), e.origin()))
.toList();
}

private static Set<CompiledConditionalPattern> compilePatternWorkset(Set<ConditionalPattern> patterns) {
return patterns.stream()
.filter(s -> s.length() > 0)
.map(this::makeResourcePattern)
.toList()
.toArray(new ResourcePattern[]{});
.flatMap(e -> {
Optional<ResourcePattern> resourcePattern = makeResourcePattern(e.pattern(), e.origin());
return resourcePattern.stream().map(pattern -> new CompiledConditionalPattern(e.condition(), pattern, e.origin()));
})
.collect(Collectors.toSet());
}

private ResourcePattern makeResourcePattern(String rawPattern) {
private static Optional<ResourcePattern> makeResourcePattern(String rawPattern, Object origin) {
String[] moduleNameWithPattern = SubstrateUtil.split(rawPattern, ":", 2);
if (moduleNameWithPattern.length < 2) {
return new ResourcePattern(null, Pattern.compile(moduleNameWithPattern[0]));
} else {
String moduleName = moduleNameWithPattern[0];
return new ResourcePattern(moduleName, Pattern.compile(moduleNameWithPattern[1]));
try {
if (moduleNameWithPattern.length < 2) {
return Optional.of(new ResourcePattern(null, Pattern.compile(moduleNameWithPattern[0])));
} else {
String moduleName = moduleNameWithPattern[0];
return Optional.of(new ResourcePattern(moduleName, Pattern.compile(moduleNameWithPattern[1])));
}
} catch (PatternSyntaxException e) {
LogUtils.warning("Skipping invalid pattern: " + rawPattern + " found in: " + origin);
return Optional.empty();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public static String validatePattern(String pattern) {
return sb.toString();
}

// check if pattern contains more than 2 consecutive characters. Example: a/***/b
// check if pattern contains more than 2 consecutive * characters. Example: a/***/b
if (threeConsecutiveStarsRegex.matcher(pattern).matches()) {
sb.append("Pattern contains more than two consecutive * characters. ");
}
Expand Down Expand Up @@ -129,7 +129,7 @@ public static String validatePattern(String pattern) {
}

if (!sb.isEmpty()) {
sb.insert(0, "Pattern " + pattern + " : ");
sb.insert(0, "Invalid pattern " + pattern + ". Reasons: ");
}

return sb.toString();
Expand Down