use of com.newrelic.weave.utils.ClassInformation in project newrelic-java-agent by newrelic.
the class WeavePackageManager method containsPossibleClassOrMethodMatch.
/**
* Quickly checks to see if the class/super class/interfaces or any of the methods in the Class represented by the
* "classByte" parameter match the Set of known classes/method signatures that constitute all of our weave classes.
* If a potential match is found it means we should continue with the normal validation process. If no match was
* found, then it's certain that this class would never match and we should end transformation of this class via the
* weaver here.
*
* @param classBytes the byte[] representing the class to check
* @param requiredClasses the set of known classes/superclasses/interfaces to compare against
* @param methodSignatures the set of all method signatures to compare against
* @param cache class cache to lookup interface annotations
* @return true if this contains a possible match, false otherwise
*/
private boolean containsPossibleClassOrMethodMatch(final String className, final byte[] classBytes, final Set<String> requiredClasses, final Set<String> methodSignatures, final ClassCache cache) {
final AtomicBoolean containsPossibleMatch = new AtomicBoolean(false);
ClassReader originalBytesReader = new ClassReader(classBytes);
originalBytesReader.accept(new ClassVisitor(WeaveUtils.ASM_API_LEVEL) {
public String[] interfaces;
private boolean isInterface = false;
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
this.interfaces = interfaces;
isInterface = (access & Opcodes.ACC_INTERFACE) == Opcodes.ACC_INTERFACE;
// Figure out if this exact class or the super class is a match
if (requiredClasses.contains(name) || requiredClasses.contains(superName)) {
containsPossibleMatch.set(true);
return;
}
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
String annotationClass = Type.getType(desc).getClassName();
if (!isInterface && requiredAnnotationClasses.contains(annotationClass)) {
// Adding class name here allows us to catch interfaces
containsPossibleMatch.set(true);
requiredClasses.add(className);
// Found a potential match. Exit early.
return null;
}
return super.visitAnnotation(desc, visible);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (containsPossibleMatch.get()) {
// This means we found a class/superclass/interface match so we should exit early here
return null;
}
// Default constructor and static initializer will be matched by visit() method above
if (!(name.equals(WeaveUtils.INIT_NAME) && desc.equals(WeaveUtils.INIT_DESC)) && !(name.equals(WeaveUtils.CLASS_INIT_NAME) && desc.equals(WeaveUtils.INIT_DESC)) && methodSignatures.contains(name + desc)) {
// If any method matches this is a potential match so we should return "true"
containsPossibleMatch.set(true);
// Skip out of this method visitor early since we've found a match
return null;
}
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if (!requiredMethodAnnotationClasses.isEmpty()) {
return new MethodVisitor(WeaveUtils.ASM_API_LEVEL, mv) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
String annotationClass = Type.getType(desc).getClassName();
if (requiredMethodAnnotationClasses.contains(annotationClass)) {
containsPossibleMatch.set(true);
// Found a potential match. Exit early.
return null;
}
return super.visitAnnotation(desc, visible);
}
};
}
return mv;
}
@Override
public void visitEnd() {
// If nothing has matched, check interface annotations
if (!isInterface && !requiredAnnotationClasses.isEmpty()) {
try {
for (String interfaceName : interfaces) {
ClassInformation interfaceInfo = cache.getClassInformation(interfaceName);
if (interfaceInfo == null) {
continue;
}
for (String interfaceAnnotationName : interfaceInfo.classAnnotationNames) {
if (requiredAnnotationClasses.contains(WeaveUtils.getClassBinaryName(interfaceAnnotationName))) {
containsPossibleMatch.set(true);
return;
}
}
}
} catch (IOException ignored) {
}
}
}
}, ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE);
return containsPossibleMatch.get();
}
Aggregations