diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java index 87b573d2b..87bfae3ed 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java @@ -64,7 +64,7 @@ public abstract class AbstractClassEnhancePluginDefine { DynamicType.Builder newClassBuilder, ClassLoader classLoader) throws PluginException; /** - * Define the classname of target class. + * Define the {@link ClassMatch} for filtering class. * * @return {@link ClassMatch} */ diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginFinder.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginFinder.java index 058df0569..3ac0158df 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginFinder.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginFinder.java @@ -1,18 +1,16 @@ package org.skywalking.apm.agent.core.plugin; -import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import net.bytebuddy.description.NamedElement; -import net.bytebuddy.description.annotation.AnnotationDescription; -import net.bytebuddy.description.annotation.AnnotationList; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.skywalking.apm.agent.core.plugin.bytebuddy.AbstractJunction; -import org.skywalking.apm.agent.core.plugin.match.AnnotationMatch; +import org.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch; import org.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.skywalking.apm.agent.core.plugin.match.IndirectMatch; import org.skywalking.apm.agent.core.plugin.match.NameMatch; import static net.bytebuddy.matcher.ElementMatchers.isInterface; @@ -36,7 +34,7 @@ public class PluginFinder { continue; } - if (match instanceof NameMatch) { + if (match instanceof IndirectMatch) { NameMatch nameMatch = (NameMatch)match; nameMatchDefine.put(nameMatch.getClassName(), plugin); } else { @@ -53,17 +51,9 @@ public class PluginFinder { } for (AbstractClassEnhancePluginDefine pluginDefine : signatureMatchDefine) { - ClassMatch classMatch = pluginDefine.enhanceClass(); - if (classMatch instanceof AnnotationMatch) { - AnnotationMatch annotationMatch = (AnnotationMatch)classMatch; - List annotationList = Arrays.asList(annotationMatch.getAnnotations()); - AnnotationList declaredAnnotations = typeDescription.getDeclaredAnnotations(); - for (AnnotationDescription annotation : declaredAnnotations) { - annotationList.remove(annotation.getAnnotationType().getActualName()); - } - if (annotationList.isEmpty()) { - return pluginDefine; - } + IndirectMatch match = (IndirectMatch)pluginDefine.enhanceClass(); + if (match.isMatch(typeDescription)) { + return pluginDefine; } } @@ -80,8 +70,8 @@ public class PluginFinder { judge = judge.and(not(isInterface())); for (AbstractClassEnhancePluginDefine define : signatureMatchDefine) { ClassMatch match = define.enhanceClass(); - if (match instanceof AnnotationMatch) { - judge = judge.or(((AnnotationMatch)match).buildJunction()); + if (match instanceof ClassAnnotationMatch) { + judge = judge.or(((ClassAnnotationMatch)match).buildJunction()); } } return judge; diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/AnnotationMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/AnnotationMatch.java deleted file mode 100644 index ecdaf4a94..000000000 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/AnnotationMatch.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.skywalking.apm.agent.core.plugin.match; - -import net.bytebuddy.matcher.ElementMatcher; - -import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; -import static net.bytebuddy.matcher.ElementMatchers.isInterface; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.not; - -/** - * @author wusheng - */ -public class AnnotationMatch extends ClassMatch { - private String[] annotations; - - public AnnotationMatch(String[] annotations) { - this.annotations = annotations; - } - - public ElementMatcher.Junction buildJunction() { - ElementMatcher.Junction junction = null; - for (String annotation : annotations) { - if (junction == null) { - junction = buildEachAnnotation(annotation); - } else { - junction = junction.and(buildEachAnnotation(annotation)); - } - } - junction = junction.and(not(isInterface())); - return junction; - } - - private ElementMatcher.Junction buildEachAnnotation(String annotationName) { - return isAnnotatedWith(named(annotationName)); - } - - public String[] getAnnotations() { - return annotations; - } -} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/ClassAnnotationMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/ClassAnnotationMatch.java new file mode 100644 index 000000000..3cc7aabb0 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/ClassAnnotationMatch.java @@ -0,0 +1,64 @@ +package org.skywalking.apm.agent.core.plugin.match; + +import java.util.Arrays; +import java.util.List; +import net.bytebuddy.description.annotation.AnnotationDescription; +import net.bytebuddy.description.annotation.AnnotationList; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; +import static net.bytebuddy.matcher.ElementMatchers.isInterface; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.not; + +/** + * Match the class by the given annotations in class. + * + * @author wusheng + */ +public class ClassAnnotationMatch implements IndirectMatch { + private String[] annotations; + + private ClassAnnotationMatch(String[] annotations) { + if (annotations == null || annotations.length == 0) { + throw new IllegalArgumentException("annotations is null"); + } + this.annotations = annotations; + } + + @Override + public ElementMatcher.Junction buildJunction() { + ElementMatcher.Junction junction = null; + for (String annotation : annotations) { + if (junction == null) { + junction = buildEachAnnotation(annotation); + } else { + junction = junction.and(buildEachAnnotation(annotation)); + } + } + junction = junction.and(not(isInterface())); + return junction; + } + + @Override + public boolean isMatch(TypeDescription typeDescription) { + List annotationList = Arrays.asList(annotations); + AnnotationList declaredAnnotations = typeDescription.getDeclaredAnnotations(); + for (AnnotationDescription annotation : declaredAnnotations) { + annotationList.remove(annotation.getAnnotationType().getActualName()); + } + if (annotationList.isEmpty()) { + return true; + } + return false; + } + + private ElementMatcher.Junction buildEachAnnotation(String annotationName) { + return isAnnotatedWith(named(annotationName)); + } + + public static ClassMatch byClassAnnotationMatch(String[] annotations) { + return new ClassAnnotationMatch(annotations); + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/ClassMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/ClassMatch.java index b1fe0140f..2ffb8ffcb 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/ClassMatch.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/ClassMatch.java @@ -3,5 +3,5 @@ package org.skywalking.apm.agent.core.plugin.match; /** * @author wusheng */ -public abstract class ClassMatch { +public interface ClassMatch { } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/HierarchyMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/HierarchyMatch.java index b9a609c79..9b72d5fcd 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/HierarchyMatch.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/HierarchyMatch.java @@ -1,22 +1,52 @@ package org.skywalking.apm.agent.core.plugin.match; +import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; +import static net.bytebuddy.matcher.ElementMatchers.hasSuperType; +import static net.bytebuddy.matcher.ElementMatchers.isInterface; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.not; + /** + * Match the class by the given super class or interfaces. + * * @author wusheng */ -public class HierarchyMatch extends ClassMatch { +public class HierarchyMatch implements IndirectMatch { private String[] parentTypes; - public HierarchyMatch(String[] parentTypes) { + private HierarchyMatch(String[] parentTypes) { + if (parentTypes == null || parentTypes.length == 0) { + throw new IllegalArgumentException("parentTypes is null"); + } this.parentTypes = parentTypes; } + @Override public ElementMatcher.Junction buildJunction() { - return null; + ElementMatcher.Junction junction = null; + for (String superTypeName : parentTypes) { + if (junction == null) { + junction = buildEachAnnotation(superTypeName); + } else { + junction = junction.and(buildEachAnnotation(superTypeName)); + } + } + junction = junction.and(not(isInterface())); + return junction; } - private ElementMatcher.Junction buildEachParent(String parentType) { - return null; + private ElementMatcher.Junction buildEachAnnotation(String superTypeName) { + return hasSuperType(named(superTypeName)); + } + + @Override + public boolean isMatch(TypeDescription typeDescription) { + return false; + } + + public static ClassMatch byHierarchyMatch(String[] parentTypes) { + return new HierarchyMatch(parentTypes); } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/IndirectMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/IndirectMatch.java new file mode 100644 index 000000000..ac036ed57 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/IndirectMatch.java @@ -0,0 +1,15 @@ +package org.skywalking.apm.agent.core.plugin.match; + +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +/** + * All implementations can't direct match the class like {@link NameMatch} did. + * + * @author wusheng + */ +public interface IndirectMatch extends ClassMatch { + ElementMatcher.Junction buildJunction(); + + boolean isMatch(TypeDescription typeDescription); +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/MethodAnnotationMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/MethodAnnotationMatch.java new file mode 100644 index 000000000..b8059aea0 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/MethodAnnotationMatch.java @@ -0,0 +1,71 @@ +package org.skywalking.apm.agent.core.plugin.match; + +import java.util.Arrays; +import java.util.List; +import net.bytebuddy.description.annotation.AnnotationDescription; +import net.bytebuddy.description.annotation.AnnotationList; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import static net.bytebuddy.matcher.ElementMatchers.declaresMethod; +import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith; +import static net.bytebuddy.matcher.ElementMatchers.isInterface; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.not; + +/** + * Match the class, which has methods with the certain annotations. + * This is a very complex match. + * + * @author wusheng + */ +public class MethodAnnotationMatch implements IndirectMatch { + private String[] annotations; + + private MethodAnnotationMatch(String[] annotations) { + if (annotations == null || annotations.length == 0) { + throw new IllegalArgumentException("annotations is null"); + } + this.annotations = annotations; + } + + @Override + public ElementMatcher.Junction buildJunction() { + ElementMatcher.Junction junction = null; + for (String annotation : annotations) { + if (junction == null) { + junction = buildEachAnnotation(annotation); + } else { + junction = junction.and(buildEachAnnotation(annotation)); + } + } + junction = declaresMethod(junction).and(not(isInterface())); + return junction; + } + + @Override + public boolean isMatch(TypeDescription typeDescription) { + for (MethodDescription.InDefinedShape methodDescription : typeDescription.getDeclaredMethods()) { + List annotationList = Arrays.asList(annotations); + + AnnotationList declaredAnnotations = methodDescription.getDeclaredAnnotations(); + for (AnnotationDescription annotation : declaredAnnotations) { + annotationList.remove(annotation.getAnnotationType().getActualName()); + } + if (annotationList.isEmpty()) { + return true; + } + } + + return false; + } + + private ElementMatcher.Junction buildEachAnnotation(String annotationName) { + return isAnnotatedWith(named(annotationName)); + } + + public static ClassMatch byMethodAnnotationMatch(String[] annotations) { + return new MethodAnnotationMatch(annotations); + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/NameMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/NameMatch.java index 1ab9c454c..48152f807 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/NameMatch.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/NameMatch.java @@ -1,12 +1,14 @@ package org.skywalking.apm.agent.core.plugin.match; /** + * Match the class with an explicit class name. + * * @author wusheng */ -public class NameMatch extends ClassMatch { +public class NameMatch implements ClassMatch { private String className; - public NameMatch(String className) { + private NameMatch(String className) { this.className = className; }