Skip to content

Commit

Permalink
Make SplitPackageProcessor configurable, add build item that allows e…
Browse files Browse the repository at this point in the history
…xtension to skip validation
  • Loading branch information
manovotn committed Jul 30, 2021
1 parent 8d49f1e commit 5ff4745
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,18 @@ public class ArcConfig {
@ConfigItem
public ArcTestConfig test;

/**
* The list of packages that will not be checked for split package issues.
* <p>
* A package string representation can be:
* <ul>
* <li>a full name of the package, i.e. {@code org.acme.foo}</li>
* <li>a package name with suffix {@code .*}, i.e. {@code org.acme.*}, which matches a package that starts with provided
* value</li>
*/
@ConfigItem
public Optional<List<String>> ignoredSplitPackages;

public final boolean isRemoveUnusedBeansFieldValid() {
return ALLOWED_REMOVE_UNUSED_BEANS_VALUES.contains(removeUnusedBeans.toLowerCase());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.quarkus.arc.deployment;

import java.util.Collection;

import io.quarkus.builder.item.MultiBuildItem;

/**
* Allows extensions to programmatically exclude certain packages from split package detection which is executed by
* {@link SplitPackageProcessor}. Extensions are encouraged to solve split package issues and this build item should
* be used primarily as temporary workaround.
* <p>
* A package string representation can be:
* <ul>
* <li>a full name of the package, i.e. {@code org.acme.foo}</li>
* <li>a package name with suffix {@code .*}, i.e. {@code org.acme.*}, which matches a package that starts with provided
* value</li>
*
*/
public final class IgnoreSplitPackageBuildItem extends MultiBuildItem {

private Collection<String> excludedPackages;

public IgnoreSplitPackageBuildItem(Collection<String> excludedPackages) {
this.excludedPackages = excludedPackages;
}

public Collection<String> getExcludedPackages() {
return excludedPackages;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package io.quarkus.arc.deployment;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
Expand All @@ -27,6 +30,10 @@
* Note that this processor is a best-effort because it only operates on {@code ApplicationArchivesBuildItem} which
* means that if a 3rd party library isn't indexed, we aren't able to detect it even though it can still be a part of
* resulting application. See also {@code io.quarkus.arc.processor.BeanArchives.IndexWrapper}.
* <p>
* This processor can be configured by users and extensions to skip validation for certain packages hence avoiding the
* warning in logs.
* See also {@link ArcConfig#ignoredSplitPackages} and {@link IgnoreSplitPackageBuildItem}
*/
public class SplitPackageProcessor {

Expand All @@ -47,9 +54,21 @@ public boolean test(String packageName) {

@BuildStep
void splitPackageDetection(ApplicationArchivesBuildItem archivesBuildItem,
ArcConfig config,
List<IgnoreSplitPackageBuildItem> excludedPackages,
// Dummy producer to make sure the build step executes
BuildProducer<ValidationPhaseBuildItem.ValidationErrorBuildItem> dummy) {
Map<String, Set<ApplicationArchive>> packageToArchiveMap = new HashMap<>();

// build up exclusion predicates from user defined config and extensions
List<Predicate> packageSkipPredicates = new ArrayList<>();
if (config.ignoredSplitPackages.isPresent()) {
packageSkipPredicates.addAll(initPredicates(config.ignoredSplitPackages.get()));
}
for (IgnoreSplitPackageBuildItem exclusionBuildItem : excludedPackages) {
packageSkipPredicates.addAll(initPredicates(exclusionBuildItem.getExcludedPackages()));
}

// for all app archives
for (ApplicationArchive archive : archivesBuildItem.getAllApplicationArchives()) {
// and for each known class in each archive
Expand All @@ -70,6 +89,18 @@ void splitPackageDetection(ApplicationArchivesBuildItem archivesBuildItem,
continue;
}

// skip packages based on pre-built predicates
boolean skipEvaluation = false;
for (Predicate<String> predicate : packageSkipPredicates) {
if (predicate.test(packageName)) {
skipEvaluation = true;
break;
}
}
if (skipEvaluation) {
continue;
}

Set<ApplicationArchive> applicationArchives = packageToArchiveMap.get(packageName);
if (applicationArchives.size() > 1) {
splitPackagesWarning.append("\n- \"" + packageName + "\" found in ");
Expand Down Expand Up @@ -107,4 +138,30 @@ void splitPackageDetection(ApplicationArchivesBuildItem archivesBuildItem,
"Following packages were detected in multiple archives: %s", splitPackagesWarning.toString());
}
}

private List<Predicate<String>> initPredicates(Collection<String> exclusions) {
final String packMatch = ".*";
List<Predicate<String>> predicates = new ArrayList<>();
for (String exclusionExpression : exclusions) {
if (exclusionExpression.endsWith(packMatch)) {
// Package ends with ".*"
final String pack = exclusionExpression.substring(0, exclusionExpression.length() - packMatch.length());
predicates.add(new Predicate<String>() {
@Override
public boolean test(String packageName) {
return packageName.startsWith(pack);
}
});
} else {
// Standard full package name
predicates.add(new Predicate<String>() {
@Override
public boolean test(String packageName) {
return packageName.equals(exclusionExpression);
}
});
}
}
return predicates;
}
}

0 comments on commit 5ff4745

Please sign in to comment.