DelegateClassAdapterpublic class DelegateClassAdapter extends org.objectweb.asm.ClassVisitor A {@link DelegateClassAdapter} can transform some methods from a class into
delegates that defer the call to an associated delegate class.
This is used to override specific methods and or all native methods in classes. |
Fields Summary |
---|
private static final String | ORIGINAL_SUFFIXSuffix added to original methods. | private static final String | CONSTRUCTOR | private static final String | CLASS_INIT | public static final String | ALL_NATIVES | private final String | mClassName | private final Set | mDelegateMethods | private final Log | mLog |
Constructors Summary |
---|
public DelegateClassAdapter(Log log, org.objectweb.asm.ClassVisitor cv, String className, Set delegateMethods)Creates a new {@link DelegateClassAdapter} that can transform some methods
from a class into delegates that defer the call to an associated delegate class.
This is used to override specific methods and or all native methods in classes.
super(Opcodes.ASM4, cv);
mLog = log;
mClassName = className;
mDelegateMethods = delegateMethods;
|
Methods Summary |
---|
public org.objectweb.asm.MethodVisitor | visitMethod(int access, java.lang.String name, java.lang.String desc, java.lang.String signature, java.lang.String[] exceptions)
boolean isStatic = (access & Opcodes.ACC_STATIC) != 0;
boolean isNative = (access & Opcodes.ACC_NATIVE) != 0;
boolean useDelegate = (isNative && mDelegateMethods.contains(ALL_NATIVES)) ||
mDelegateMethods.contains(name);
if (!useDelegate) {
// Not creating a delegate for this method, pass it as-is from the reader to the writer.
return super.visitMethod(access, name, desc, signature, exceptions);
}
if (CONSTRUCTOR.equals(name) || CLASS_INIT.equals(name)) {
// We don't currently support generating delegates for constructors.
throw new UnsupportedOperationException(
String.format(
"Delegate doesn't support overriding constructor %1$s:%2$s(%3$s)", //$NON-NLS-1$
mClassName, name, desc));
}
if (isNative) {
// Remove native flag
access = access & ~Opcodes.ACC_NATIVE;
MethodVisitor mwDelegate = super.visitMethod(access, name, desc, signature, exceptions);
DelegateMethodAdapter a = new DelegateMethodAdapter(
mLog, null, mwDelegate, mClassName, name, desc, isStatic);
// A native has no code to visit, so we need to generate it directly.
a.generateDelegateCode();
return mwDelegate;
}
// Given a non-native SomeClass.MethodName(), we want to generate 2 methods:
// - A copy of the original method named SomeClass.MethodName_Original().
// The content is the original method as-is from the reader.
// - A brand new implementation of SomeClass.MethodName() which calls to a
// non-existing method named SomeClass_Delegate.MethodName().
// The implementation of this 'delegate' method is done in layoutlib_bridge.
int accessDelegate = access;
access = access & ~Opcodes.ACC_PRIVATE; // If private, make it package protected.
MethodVisitor mwOriginal = super.visitMethod(access, name + ORIGINAL_SUFFIX,
desc, signature, exceptions);
MethodVisitor mwDelegate = super.visitMethod(accessDelegate, name,
desc, signature, exceptions);
return new DelegateMethodAdapter(
mLog, mwOriginal, mwDelegate, mClassName, name, desc, isStatic);
|
|