Invoker adapter interface support

This commit is contained in:
Clisprail
2014-04-29 01:42:38 +02:00
parent f5e09e5631
commit 98ac8ab301
4 changed files with 60 additions and 23 deletions
@@ -22,16 +22,27 @@ public class AddInvokerAdapter implements Opcodes, Injectable {
private String argsDesc;
private String returnDesc;
private String methodName;
private boolean isInterface;
private String instanceCast;
private String mName;
private String mDesc;
private boolean isStatic;
public AddInvokerAdapter(final ClassNode methodLocation,
final ClassNode into, final MethodNode mn, final String argsDesc,
final String returnDesc, final String methodName) {
final ClassNode into, final MethodNode mn, final String mName, final String mDesc, final String argsDesc,
final String returnDesc, final String methodName,
boolean isInterface, String instanceCast) {
this.into = into;
this.methodLocation = methodLocation;
this.mName = mName;
this.mDesc = mDesc;
this.mn = mn;
this.argsDesc = argsDesc;
this.returnDesc = returnDesc;
this.methodName = methodName;
this.isInterface = isInterface;
this.instanceCast = instanceCast;
}
@Override
@@ -39,28 +50,41 @@ public class AddInvokerAdapter implements Opcodes, Injectable {
MethodNode m = new MethodNode(ACC_PUBLIC, this.methodName,
this.argsDesc + this.returnDesc, null, null);
boolean isStatic = (this.mn.access & ACC_STATIC) != 0;
if(!isInterface) {
isStatic = (this.mn.access & ACC_STATIC) != 0;
if (!Modifier.isPublic(mn.access)) {
if (Modifier.isPrivate(mn.access)) {
mn.access = mn.access & (~ACC_PRIVATE);
}
if (Modifier.isProtected(mn.access)) {
mn.access = mn.access & (~ACC_PROTECTED);
}
mn.access = mn.access | ACC_PUBLIC;
}
}
if(!Modifier.isPublic(mn.access)) {
if(Modifier.isPrivate(mn.access)) {
mn.access = mn.access & (~ACC_PRIVATE);
}
if(Modifier.isProtected(mn.access)) {
mn.access = mn.access & (~ACC_PROTECTED);
}
mn.access = mn.access | ACC_PUBLIC;
if(!isStatic || isInterface) {
m.visitVarInsn(ALOAD, 0);
}
if (!isStatic)
m.visitVarInsn(ALOAD, 0);
if (!this.argsDesc.equals("()"))
for (int i = 1; i < this.argsDesc.length() - 1; i++)
if (!this.argsDesc.equals("()")) {
for (int i = 1; i < this.argsDesc.length() - 1; i++) {
m.visitVarInsn(ASMUtils.getLoadOpcode(this.argsDesc.substring(
i, i + 1)), i);
}
}
if(instanceCast != null) {
m.visitTypeInsn(CHECKCAST, instanceCast);
}
m.visitMethodInsn(isStatic ? INVOKESTATIC : INVOKEVIRTUAL,
methodLocation.name, mn.name, mn.desc);
if(isInterface) {
m.visitMethodInsn(INVOKEINTERFACE, instanceCast, mName, mDesc);
} else {
m.visitMethodInsn(isStatic ? INVOKESTATIC : INVOKEVIRTUAL, methodLocation.name, mn.name, mn.desc);
}
if (this.returnDesc.contains("L")) {
if (!this.returnDesc.contains("[")) {
m.visitTypeInsn(CHECKCAST, this.returnDesc
@@ -20,21 +20,31 @@ public class Invoker implements Injectable {
private String argsDesc;
private String returnDesc;
private String methodName;
private boolean isInterface;
private String instanceCast;
private String mName;
private String mDesc;
public Invoker(String methodLoc, String invMethName, String argsDesc,
String returnDesc, String methodName) {
this(methodLoc, methodLoc, invMethName, argsDesc, returnDesc,
methodName);
methodName, false, null);
}
public Invoker(String into, String methodLoc, String invMethName,
String argsDesc, String returnDesc, String methodName) {
String argsDesc, String returnDesc, String methodName, boolean isInterface, String instanceCast) {
this.into = ASMUtils.getClass(into);
this.methodLocation = ASMUtils.getClass(methodLoc);
this.mn = getMethod(this.methodLocation, invMethName, argsDesc);
this.returnDesc = returnDesc;
this.methodName = methodName;
this.argsDesc = argsDesc;
this.isInterface = isInterface;
this.instanceCast = instanceCast;
this.mName = invMethName;
this.mDesc = argsDesc + returnDesc;
}
private static MethodNode getMethod(ClassNode into, String name, String desc) {
@@ -63,8 +73,8 @@ public class Invoker implements Injectable {
* @return AddInvokerAdapter
*/
public AddInvokerAdapter getAdapter() {
return new AddInvokerAdapter(this.methodLocation, this.into, this.mn,
this.argsDesc, this.returnDesc, this.methodName);
return new AddInvokerAdapter(this.methodLocation, this.into, this.mn, this.mName, this.mDesc,
this.argsDesc, this.returnDesc, this.methodName, this.isInterface, this.instanceCast);
}
}
@@ -185,7 +185,7 @@ public class JSONHookParser extends HookParser {
String clazz = o.containsKey("class") ? this.get(o, "class") : interfaces.get(this.get(o, "accessor"));
String into = o.containsKey("into") ? this.get(o, "into") : clazz;
i[j] = new Invoker(into, clazz, this.get(o, "invokemethod"), this.get(o, "argdesc"), this.get(o, "desc"), this.get(o, "method"));
i[j] = new Invoker(into, clazz, this.get(o, "invokemethod"), this.get(o, "argdesc"), this.get(o, "desc"), this.get(o, "method"), false, null);
}
return i;
}
@@ -345,9 +345,12 @@ public class XMLHookParser extends HookParser {
final String argsDesc = getValue("argsdesc", addInvoker);
String returnDesc = isSet("desc", addInvoker) ? resolveDesc(getValue(
"desc", addInvoker)) : null;
final boolean isInterface = isSet("interface", addInvoker) ? Boolean.parseBoolean(getValue("interface", addInvoker)) : false;
final String instanceCast = isSet("instancecast", addInvoker) ? getValue("instancecast", addInvoker) : null;
final Invoker invoker = new Invoker(into, className, invMethodName,
argsDesc, returnDesc, methodName);
argsDesc, returnDesc, methodName, isInterface, instanceCast);
invokerList.add(invoker);
}
return invokerList.toArray(new Invoker[invokerList.size()]);