Skip to content

Commit 76e8487

Browse files
committed
Print warning if provided pattern is invalid
1 parent f8a5bef commit 76e8487

File tree

8 files changed

+62
-51
lines changed

8 files changed

+62
-51
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -56,7 +56,7 @@ static RuntimeResourceSupport<ConfigurationCondition> singleton() {
5656

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

59-
void ignoreResources(C condition, String pattern);
59+
void ignoreResources(C condition, String pattern, Object origin);
6060

6161
void addResourceBundles(C condition, String name);
6262

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -113,7 +113,7 @@ public void injectResource(Module module, String resourcePath, byte[] resourceCo
113113
}
114114

115115
@Override
116-
public void ignoreResources(UnresolvedConfigurationCondition condition, String pattern) {
116+
public void ignoreResources(UnresolvedConfigurationCondition condition, String pattern, Object origin) {
117117
ignoredResources.add(pattern);
118118
}
119119

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/LegacyResourceConfigurationParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -95,7 +95,7 @@ private void parseResourcesObject(Object resourcesObject, Object origin) {
9595
if (excludesObject != null) {
9696
List<Object> excludes = asList(excludesObject, "Attribute 'excludes' must be a list of resources");
9797
for (Object object : excludes) {
98-
parsePatternEntry(object, registry::ignoreResources, null, "'excludes' list");
98+
parsePatternEntry(object, (condition, pattern) -> registry.ignoreResources(condition, pattern, origin), null, "'excludes' list");
9999
}
100100
}
101101
} else { // Old format: may be deprecated in future versions

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/ResourcesRegistry.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,7 @@ default void addResources(C condition, String pattern) {
5151
}
5252

5353
@Override
54-
void ignoreResources(C condition, String pattern);
54+
void ignoreResources(C condition, String pattern, Object origin);
5555

5656
@Override
5757
void addResourceBundles(C condition, String name);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -94,7 +94,7 @@ public void injectResource(Module module, String resourcePath, byte[] resourceCo
9494
}
9595

9696
@Override
97-
public void ignoreResources(UnresolvedConfigurationCondition condition, String pattern) {
97+
public void ignoreResources(UnresolvedConfigurationCondition condition, String pattern, Object origin) {
9898
configuration.ignoreResourcePattern(condition, pattern);
9999
}
100100

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -38,8 +38,9 @@
3838
import org.graalvm.nativeimage.Platform;
3939
import org.graalvm.nativeimage.Platforms;
4040

41-
import com.oracle.svm.core.util.UserError;
41+
import com.oracle.svm.core.ClassLoaderSupport;
4242
import com.oracle.svm.util.GlobUtils;
43+
import com.oracle.svm.util.LogUtils;
4344
import com.oracle.svm.util.StringUtil;
4445

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

108-
List<String> invalidPatterns = classifyPatterns(patterns, doubleStarPatterns, starPatterns, noStarPatterns);
109-
if (!invalidPatterns.isEmpty()) {
110-
StringBuilder sb = new StringBuilder("Error: invalid glob patterns found:" + System.lineSeparator());
111-
invalidPatterns.forEach(msg -> sb.append(msg).append(System.lineSeparator()));
112-
113-
throw UserError.abort(sb.toString());
109+
List<String> invalidPatternsErrors = classifyPatterns(patterns, doubleStarPatterns, starPatterns, noStarPatterns);
110+
if (!invalidPatternsErrors.isEmpty()) {
111+
invalidPatternsErrors.forEach(LogUtils::warning);
114112
}
115113

116114
/* sort patterns in the groups based on generality */
@@ -221,7 +219,12 @@ private static <C> List<String> classifyPatterns(List<GlobWithInfo<C>> patterns,
221219
/* validate patterns */
222220
String error = GlobUtils.validatePattern(patternWithInfo.pattern());
223221
if (!error.isEmpty()) {
224-
invalidPatterns.add(error);
222+
if (patternWithInfo.additionalContent() instanceof ClassLoaderSupport.ConditionWithOrigin conditionWithOrigin) {
223+
invalidPatterns.add(error + "Pattern is from: " + conditionWithOrigin.origin());
224+
} else {
225+
invalidPatterns.add(error);
226+
}
227+
225228
continue;
226229
}
227230

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

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -53,6 +53,7 @@
5353
import java.util.concurrent.TimeUnit;
5454
import java.util.concurrent.atomic.LongAdder;
5555
import java.util.regex.Pattern;
56+
import java.util.regex.PatternSyntaxException;
5657
import java.util.stream.Collectors;
5758

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

170171
private Set<ConditionalPattern> resourcePatternWorkSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
171172
private Set<ConditionalPattern> globWorkSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
172-
private final Set<String> excludedResourcePatterns = Collections.newSetFromMap(new ConcurrentHashMap<>());
173+
private final Set<ConditionalPattern> excludedResourcePatterns = Collections.newSetFromMap(new ConcurrentHashMap<>());
173174

174175
private int loadedConfigurations;
175176
private ImageClassLoader imageClassLoader;
@@ -233,11 +234,11 @@ public void injectResource(Module module, String resourcePath, byte[] resourceCo
233234
}
234235

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

240-
excludedResourcePatterns.add(pattern);
241+
excludedResourcePatterns.add(new ConditionalPattern(condition, pattern, origin));
241242
});
242243
}
243244

@@ -442,17 +443,11 @@ public void beforeAnalysis(BeforeAnalysisAccess a) {
442443
}
443444

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

454-
excludedResourcePatterns.addAll(Options.ExcludeResources.getValue().values());
455-
ResourcePattern[] excludePatterns = compilePatterns(excludedResourcePatterns);
449+
excludedResourcePatterns.addAll(getPatternsFromOption(Options.ExcludeResources.getValue()));
450+
Set<CompiledConditionalPattern> excludePatterns = compilePatternWorkset(excludedResourcePatterns);
456451

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

489484
private static final class ResourceCollectorImpl extends ConditionalConfigurationRegistry implements ResourceCollector {
490485
private final Set<CompiledConditionalPattern> includePatterns;
491-
private final ResourcePattern[] excludePatterns;
486+
private final Set<CompiledConditionalPattern> excludePatterns;
492487
private static final int WATCHDOG_RESET_AFTER_EVERY_N_RESOURCES = 1000;
493488
private static final int WATCHDOG_INITIAL_WARNING_AFTER_N_SECONDS = 60;
494489
private static final int WATCHDOG_WARNING_AFTER_EVERY_N_SECONDS = 20;
@@ -497,7 +492,7 @@ private static final class ResourceCollectorImpl extends ConditionalConfiguratio
497492
private volatile String currentlyProcessedEntry;
498493
ScheduledExecutorService scheduledExecutor;
499494

500-
private ResourceCollectorImpl(Set<CompiledConditionalPattern> includePatterns, ResourcePattern[] excludePatterns) {
495+
private ResourceCollectorImpl(Set<CompiledConditionalPattern> includePatterns, Set<CompiledConditionalPattern> excludePatterns) {
501496
this.includePatterns = includePatterns;
502497
this.excludePatterns = excludePatterns;
503498

@@ -542,11 +537,11 @@ public List<ConditionWithOrigin> isIncluded(Module module, String resourceName,
542537
* Once migration to glob patterns is done, this code should be removed (include and
543538
* exclude patterns)
544539
*/
545-
for (ResourcePattern rp : excludePatterns) {
546-
if (!rp.moduleNameMatches(moduleName)) {
540+
for (CompiledConditionalPattern rp : excludePatterns) {
541+
if (!rp.compiledPattern.moduleNameMatches(moduleName)) {
547542
continue;
548543
}
549-
if (rp.pattern.matcher(resourceName).matches()) {
544+
if (rp.compiledPattern().pattern.matcher(resourceName).matches()) {
550545
return List.of(); // nothing should match excluded resource
551546
}
552547
}
@@ -606,21 +601,34 @@ public void registerIncludePattern(ConfigurationCondition condition, String modu
606601
}
607602
}
608603

609-
private ResourcePattern[] compilePatterns(Set<String> patterns) {
604+
private static List<ConditionalPattern> getPatternsFromOption(AccumulatingLocatableMultiOptionValue.Strings option) {
605+
return option
606+
.getValuesWithOrigins()
607+
.map(e -> new ConditionalPattern(ConfigurationCondition.alwaysTrue(), e.value(), e.origin()))
608+
.toList();
609+
}
610+
611+
private static Set<CompiledConditionalPattern> compilePatternWorkset(Set<ConditionalPattern> patterns) {
610612
return patterns.stream()
611-
.filter(s -> s.length() > 0)
612-
.map(this::makeResourcePattern)
613-
.toList()
614-
.toArray(new ResourcePattern[]{});
613+
.flatMap(e -> {
614+
Optional<ResourcePattern> resourcePattern = makeResourcePattern(e.pattern(), e.origin());
615+
return resourcePattern.stream().map(pattern -> new CompiledConditionalPattern(e.condition(), pattern, e.origin()));
616+
})
617+
.collect(Collectors.toSet());
615618
}
616619

617-
private ResourcePattern makeResourcePattern(String rawPattern) {
620+
private static Optional<ResourcePattern> makeResourcePattern(String rawPattern, Object origin) {
618621
String[] moduleNameWithPattern = SubstrateUtil.split(rawPattern, ":", 2);
619-
if (moduleNameWithPattern.length < 2) {
620-
return new ResourcePattern(null, Pattern.compile(moduleNameWithPattern[0]));
621-
} else {
622-
String moduleName = moduleNameWithPattern[0];
623-
return new ResourcePattern(moduleName, Pattern.compile(moduleNameWithPattern[1]));
622+
try {
623+
if (moduleNameWithPattern.length < 2) {
624+
return Optional.of(new ResourcePattern(null, Pattern.compile(moduleNameWithPattern[0])));
625+
} else {
626+
String moduleName = moduleNameWithPattern[0];
627+
return Optional.of(new ResourcePattern(moduleName, Pattern.compile(moduleNameWithPattern[1])));
628+
}
629+
} catch (PatternSyntaxException e) {
630+
LogUtils.warning("Skipping invalid pattern: " + rawPattern + " found in: " + origin);
631+
return Optional.empty();
624632
}
625633
}
626634

substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/GlobUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public static String validatePattern(String pattern) {
7979
return sb.toString();
8080
}
8181

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

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

135135
return sb.toString();

0 commit comments

Comments
 (0)