From 98ac8ab3019a126b01e5e12727b719128a3664b3 Mon Sep 17 00:00:00 2001 From: Clisprail Date: Tue, 29 Apr 2014 01:42:38 +0200 Subject: [PATCH] Invoker adapter interface support --- .../core/asm/adapters/AddInvokerAdapter.java | 58 +++++++++++++------ .../parabot/core/asm/wrappers/Invoker.java | 18 ++++-- .../core/parsers/hooks/JSONHookParser.java | 2 +- .../core/parsers/hooks/XMLHookParser.java | 5 +- 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/parabotv2/src/org/parabot/core/asm/adapters/AddInvokerAdapter.java b/parabotv2/src/org/parabot/core/asm/adapters/AddInvokerAdapter.java index b08d94f..2e35a35 100644 --- a/parabotv2/src/org/parabot/core/asm/adapters/AddInvokerAdapter.java +++ b/parabotv2/src/org/parabot/core/asm/adapters/AddInvokerAdapter.java @@ -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 diff --git a/parabotv2/src/org/parabot/core/asm/wrappers/Invoker.java b/parabotv2/src/org/parabot/core/asm/wrappers/Invoker.java index c8b978e..6396df7 100644 --- a/parabotv2/src/org/parabot/core/asm/wrappers/Invoker.java +++ b/parabotv2/src/org/parabot/core/asm/wrappers/Invoker.java @@ -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); } } diff --git a/parabotv2/src/org/parabot/core/parsers/hooks/JSONHookParser.java b/parabotv2/src/org/parabot/core/parsers/hooks/JSONHookParser.java index 2ff494c..93686bb 100644 --- a/parabotv2/src/org/parabot/core/parsers/hooks/JSONHookParser.java +++ b/parabotv2/src/org/parabot/core/parsers/hooks/JSONHookParser.java @@ -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; } diff --git a/parabotv2/src/org/parabot/core/parsers/hooks/XMLHookParser.java b/parabotv2/src/org/parabot/core/parsers/hooks/XMLHookParser.java index 54a67f4..15b5ccd 100644 --- a/parabotv2/src/org/parabot/core/parsers/hooks/XMLHookParser.java +++ b/parabotv2/src/org/parabot/core/parsers/hooks/XMLHookParser.java @@ -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()]);