From 467e518e4689426b2a99eac32fee86b76788d9d2 Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Mon, 30 Mar 2026 15:30:23 +0300 Subject: [PATCH] Decompose dicjunction matchers --- .../agent/builder/AgentBuilderUtil.java | 58 +++++++++++++++---- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/javaagent-tooling/src/main/java/net/bytebuddy/agent/builder/AgentBuilderUtil.java b/javaagent-tooling/src/main/java/net/bytebuddy/agent/builder/AgentBuilderUtil.java index 82df2dd6b5f9..e6ccfbce6561 100644 --- a/javaagent-tooling/src/main/java/net/bytebuddy/agent/builder/AgentBuilderUtil.java +++ b/javaagent-tooling/src/main/java/net/bytebuddy/agent/builder/AgentBuilderUtil.java @@ -6,6 +6,7 @@ package net.bytebuddy.agent.builder; import static java.util.Collections.emptyIterator; +import static java.util.Collections.singleton; import static java.util.logging.Level.FINE; import io.opentelemetry.javaagent.extension.matcher.internal.DelegatingMatcher; @@ -48,6 +49,8 @@ public class AgentBuilderUtil { private static final Field erasureMatcherField = getField(ErasureMatcher.class, "matcher"); private static final Field conjunctionMatchersField = getField(ElementMatcher.Junction.Conjunction.class, "matchers"); + private static final Field disjunctionMatchersField = + getField(ElementMatcher.Junction.Disjunction.class, "matchers"); private static final Field stringMatcherValueField = getField(StringMatcher.class, "value"); private static final Field stringMatcherModeField = getField(StringMatcher.class, "mode"); private static final Field stringSetMatcherValuesField = @@ -173,11 +176,37 @@ private static Result inspect(ElementMatcher matcher) throws Exception { List> matchers = getDelegateMatchers((ElementMatcher.Junction.Conjunction) matcher); for (ElementMatcher elementMatcher : matchers) { + // For conjunction to match all elements need to match, we can return result for any element + // here since we are using it as a negative match - if it does not match the whole matcher + // can't match. Result result = inspect(elementMatcher); if (result != null) { return result; } } + } else if (matcher instanceof ElementMatcher.Junction.Disjunction) { + List> matchers = + getDelegateMatchers((ElementMatcher.Junction.Disjunction) matcher); + boolean subtype = false; + Set names = new HashSet<>(); + boolean failed = false; + for (ElementMatcher elementMatcher : matchers) { + // For disjunction to match at least one element needs to match, we need to inspect all + // elements and combine results to be able to tell whether the whole matcher could match. + Result result = inspect(elementMatcher); + if (result == null) { + failed = true; + break; + } + // Subtype matcher covers named matcher, if we have at least one subtype matcher we can + // treat all named matchers as subtype matchers, if we have only named matchers we can treat + // them as named matchers. + subtype |= result.subtype; + names.addAll(result.names); + } + if (!failed) { + return subtype ? Result.subtype(names) : Result.named(names); + } } return null; @@ -207,19 +236,17 @@ private Result(boolean subtype) { this.subtype = subtype; } - private Result() { - this(false); - } - @Nullable static Result subtype(@Nullable Result value) { if (value == null) { return null; } + return subtype(value.names); + } - Result result = new Result(true); - result.names.addAll(value.names); - return result; + @Nullable + static Result subtype(@Nullable Set value) { + return result(true, value); } @Nullable @@ -227,17 +254,20 @@ static Result named(@Nullable String value) { if (value == null) { return null; } - Result result = new Result(); - result.names.add(value); - return result; + return named(singleton(value)); } @Nullable static Result named(@Nullable Set value) { + return result(false, value); + } + + @Nullable + private static Result result(boolean subtype, @Nullable Set value) { if (value == null || value.isEmpty()) { return null; } - Result result = new Result(); + Result result = new Result(subtype); result.names.addAll(value); return result; } @@ -283,6 +313,12 @@ private static List> getDelegateMatchers( return (List>) conjunctionMatchersField.get(matcher); } + @SuppressWarnings("unchecked") // casting reflection result + private static List> getDelegateMatchers( + ElementMatcher.Junction.Disjunction matcher) throws Exception { + return (List>) disjunctionMatchersField.get(matcher); + } + /** * @return the value given string matcher matches when matcher mode is * StringMatcher.Mode.EQUALS_FULLY, null otherwise