org.test4j.mock.faking.meta.ClassMeta Maven / Gradle / Ivy
package org.test4j.mock.faking.meta;
import g_asm.org.objectweb.asm.AnnotationVisitor;
import g_asm.org.objectweb.asm.ClassReader;
import g_asm.org.objectweb.asm.ClassVisitor;
import g_asm.org.objectweb.asm.MethodVisitor;
import org.test4j.mock.faking.modifier.FakeTransformer;
import org.test4j.mock.faking.util.ClassFile;
import org.test4j.mock.faking.util.TypeUtility;
import java.util.ArrayList;
import java.util.List;
import static org.test4j.mock.faking.util.AsmConstant.acceptOptions;
import static org.test4j.mock.faking.util.AsmConstant.api_code;
import static org.test4j.mock.faking.util.ClassFile.notObjectOrProxy;
import static org.test4j.mock.faking.util.TypeDesc.T_Mock;
/**
* 从class文件中解析出的元数据
*
* @author darui.wu
*/
@SuppressWarnings({"unused", "rawtypes"})
public final class ClassMeta {
private final Class declareToFake;
/**
* 类中定义的方法列表
*/
public final List methods;
public ClassMeta(Class declareToFake, Class fakeClass) {
this.declareToFake = declareToFake;
byte[] bytes = ClassFile.readBytesFromClassFile(fakeClass);
ClassReader classReader = new ClassReader(bytes);
this.methods = this.findMethods(classReader);
}
private List findMethods(ClassReader classReader) {
List methods = new ArrayList<>();
classReader.accept(new ClassVisitor(api_code) {
@Override
public MethodVisitor visitMethod(int access, String methodName, String paraDesc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, methodName, paraDesc, signature, exceptions);
return new MethodVisitor(api_code, mv) {
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
if (!T_Mock.DESC.equals(descriptor)) {
return super.visitAnnotation(descriptor, visible);
}
methods.add(ClassMeta.this.buildMethodId(methodName, paraDesc));
return super.visitAnnotation(descriptor, visible);
}
};
}
}, acceptOptions);
return methods;
}
private MethodId buildMethodId(String name, String descriptor) {
String methodDesc = MethodId.buildMethodDesc(name, descriptor);
Class superClass = this.declareToFake;
while (notObjectOrProxy(superClass)) {
String classDesc = TypeUtility.classPath(superClass);
Boolean isStatic = FakeTransformer.findMethodInFaked(classDesc, methodDesc);
if (isStatic == null) {
superClass = superClass.getSuperclass();
continue;
}
return new MethodId(isStatic ? superClass : declareToFake, superClass, name, descriptor);
}
/*
* 未找到实现方法, 标识为抽象方法
*/
return new MethodId(declareToFake, null, name, descriptor);
}
}