Search in sources :

Example 1 with MethodAdapter

use of jodd.asm.MethodAdapter in project jodd by oblac.

the class ProxyAspectData method readAdviceData.

// ---------------------------------------------------------------- read
/**
	 * Parse advice class to gather some advice data. Should be called before any advice use.
	 * Must be called only *once* per advice.
	 */
private void readAdviceData() {
    if (ready) {
        return;
    }
    adviceClassReader.accept(new EmptyClassVisitor() {

        /**
			 * Stores advice reference.
			 */
        @Override
        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
            adviceReference = name;
            super.visit(version, access, name, signature, superName, interfaces);
        }

        /**
			 * Prevents advice to have inner classes.
			 */
        @Override
        public void visitInnerClass(String name, String outerName, String innerName, int access) {
            if (outerName.equals(adviceReference)) {
                throw new ProxettaException("Proxetta doesn't allow inner classes in/for advice: " + advice.getName());
            }
            super.visitInnerClass(name, outerName, innerName, access);
        }

        /**
			 * Clones advices fields to destination.
			 */
        @Override
        public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
            // [A5]
            wd.dest.visitField(access, adviceFieldName(name, aspectIndex), desc, signature, value);
            return super.visitField(access, name, desc, signature, value);
        }

        /**
			 * Copies advices methods to destination.
			 */
        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            if (name.equals(CLINIT)) {
                // [A6]
                if (!desc.equals(DESC_VOID)) {
                    throw new ProxettaException("Invalid static initialization block description for advice: " + advice.getName());
                }
                name = clinitMethodName + methodDivider + aspectIndex;
                access |= AsmUtil.ACC_PRIVATE | AsmUtil.ACC_FINAL;
                wd.addAdviceClinitMethod(name);
                return new MethodAdapter(wd.dest.visitMethod(access, name, desc, signature, exceptions)) {

                    @Override
                    public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
                    }

                    @Override
                    public void visitLineNumber(int line, Label start) {
                    }

                    @Override
                    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isInterface) {
                        if (opcode == INVOKESTATIC) {
                            if (owner.equals(adviceReference)) {
                                owner = wd.thisReference;
                                name = adviceMethodName(name, aspectIndex);
                            }
                        }
                        super.visitMethodInsn(opcode, owner, name, desc, isInterface);
                    }

                    @Override
                    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
                        // [F6]
                        if (owner.equals(adviceReference)) {
                            // [F5]
                            owner = wd.thisReference;
                            name = adviceFieldName(name, aspectIndex);
                        }
                        super.visitFieldInsn(opcode, owner, name, desc);
                    }
                };
            } else if (name.equals(INIT)) {
                // [A7]
                if (!desc.equals(DESC_VOID)) {
                    throw new ProxettaException("Advices can have only default constructors. Invalid advice: " + advice.getName());
                }
                name = initMethodName + methodDivider + aspectIndex;
                access = ProxettaAsmUtil.makePrivateFinalAccess(access);
                wd.addAdviceInitMethod(name);
                return new MethodAdapter(wd.dest.visitMethod(access, name, desc, signature, exceptions)) {

                    @Override
                    public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
                    }

                    @Override
                    public void visitLineNumber(int line, Label start) {
                    }

                    // used to detect and to ignore the first super call()
                    int state;

                    @Override
                    public void visitVarInsn(int opcode, int var) {
                        // [F7]
                        if ((state == 0) && (opcode == ALOAD) && (var == 0)) {
                            state++;
                            return;
                        }
                        super.visitVarInsn(opcode, var);
                    }

                    @Override
                    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isInterface) {
                        if ((state == 1) && (opcode == INVOKESPECIAL)) {
                            state++;
                            return;
                        }
                        if ((opcode == INVOKEVIRTUAL) || (opcode == INVOKEINTERFACE)) {
                            if (owner.equals(adviceReference)) {
                                owner = wd.thisReference;
                                name = adviceMethodName(name, aspectIndex);
                            }
                        } else if (opcode == INVOKESTATIC) {
                            if (owner.equals(adviceReference)) {
                                owner = wd.thisReference;
                                name = adviceMethodName(name, aspectIndex);
                            }
                        }
                        super.visitMethodInsn(opcode, owner, name, desc, isInterface);
                    }

                    @Override
                    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
                        // [F7]
                        if (owner.equals(adviceReference)) {
                            // [F5]
                            owner = wd.thisReference;
                            name = adviceFieldName(name, aspectIndex);
                        }
                        super.visitFieldInsn(opcode, owner, name, desc);
                    }
                };
            } else // other methods
            if (!name.equals(executeMethodName)) {
                name = adviceMethodName(name, aspectIndex);
                return new MethodAdapter(wd.dest.visitMethod(access, name, desc, signature, exceptions)) {

                    @Override
                    public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
                    }

                    @Override
                    public void visitLineNumber(int line, Label start) {
                    }

                    @Override
                    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean isInterface) {
                        if ((opcode == INVOKEVIRTUAL) || (opcode == INVOKEINTERFACE)) {
                            if (owner.equals(adviceReference)) {
                                owner = wd.thisReference;
                                name = adviceMethodName(name, aspectIndex);
                            }
                        } else if (opcode == INVOKESTATIC || opcode == INVOKESPECIAL) {
                            if (owner.equals(adviceReference)) {
                                owner = wd.thisReference;
                                name = adviceMethodName(name, aspectIndex);
                            }
                        }
                        super.visitMethodInsn(opcode, owner, name, desc, isInterface);
                    }

                    @Override
                    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
                        // replace field references
                        if (owner.equals(adviceReference)) {
                            owner = wd.thisReference;
                            name = adviceFieldName(name, aspectIndex);
                        }
                        super.visitFieldInsn(opcode, owner, name, desc);
                    }
                };
            }
            //return new MethodAdapter(new EmptyMethodVisitor()) {		// toask may we replace this with the following code?
            return new EmptyMethodVisitor() {

                @Override
                public void visitVarInsn(int opcode, int var) {
                    if (isStoreOpcode(opcode)) {
                        if (var > maxLocalVarOffset) {
                            // find max local var offset
                            maxLocalVarOffset = var;
                        }
                    }
                    super.visitVarInsn(opcode, var);
                }
            };
        //					return super.visitMethod(access, name, desc, signature, exceptions);
        }
    }, 0);
    // increment offset by 2 because var on last index may be a dword value
    maxLocalVarOffset += 2;
    ready = true;
}
Also used : ProxettaException(jodd.proxetta.ProxettaException) Label(jodd.asm5.Label) FieldVisitor(jodd.asm5.FieldVisitor) EmptyClassVisitor(jodd.asm.EmptyClassVisitor) EmptyMethodVisitor(jodd.asm.EmptyMethodVisitor) MethodVisitor(jodd.asm5.MethodVisitor) MethodAdapter(jodd.asm.MethodAdapter) EmptyMethodVisitor(jodd.asm.EmptyMethodVisitor)

Aggregations

EmptyClassVisitor (jodd.asm.EmptyClassVisitor)1 EmptyMethodVisitor (jodd.asm.EmptyMethodVisitor)1 MethodAdapter (jodd.asm.MethodAdapter)1 FieldVisitor (jodd.asm5.FieldVisitor)1 Label (jodd.asm5.Label)1 MethodVisitor (jodd.asm5.MethodVisitor)1 ProxettaException (jodd.proxetta.ProxettaException)1