org.boretti.drools.integration.drools5.DroolsAddConstructorMethodVisitor.java Source code

Java tutorial

Introduction

Here is the source code for org.boretti.drools.integration.drools5.DroolsAddConstructorMethodVisitor.java

Source

/*
Drools5 Integration Helper
Copyright (C) 2009  Mathieu Boretti mathieu.boretti@gmail.com
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
 */
package org.boretti.drools.integration.drools5;

import org.boretti.drools.integration.drools5.annotations.DroolsResourceName;
import org.boretti.drools.integration.drools5.annotations.DroolsResourceType;
import org.drools.RuleBase;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.commons.AdviceAdapter;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

/**
 * @author mbo
 * @since 1.0.0
 */
class DroolsAddConstructorMethodVisitor extends AdviceAdapter {

    private String parent;

    /* (non-Javadoc)
     * @see org.objectweb.asm.MethodAdapter#visitParameterAnnotation(int, java.lang.String, boolean)
     */
    @Override
    public AnnotationVisitor visitParameterAnnotation(int idx, String name, boolean arg2) {
        if (Type.getType(name).getClassName().equals(Type.getType(DroolsResourceName.class).getClassName())) {
            if (arguments[idx].equals(Type.getType(String.class))) {
                if (overrideNameJVMIndex >= 0) {
                    droolsGoalExecutionLog.getLogs().add(new DroolsGoalExecutionLog(
                            droolsGoalExecutionLog.getFileName(), droolsGoalExecutionLog.getAction(),
                            "Warning, @DroolsResourceName can't be used more than one time in the same constructor"));
                } else {
                    droolsGoalExecutionLog.getLogs()
                            .add(new DroolsGoalExecutionLog(droolsGoalExecutionLog.getFileName(),
                                    droolsGoalExecutionLog.getAction(),
                                    "This constructor will use resource Location override"));
                    overrideNameJVMIndex = getJVMIndex(idx);
                }
            } else {
                droolsGoalExecutionLog.getLogs()
                        .add(new DroolsGoalExecutionLog(droolsGoalExecutionLog.getFileName(),
                                droolsGoalExecutionLog.getAction(),
                                "Warning, @DroolsResourceName must be used on String parameter"));
            }
        } else if (Type.getType(name).getClassName()
                .equals(Type.getType(DroolsResourceType.class).getClassName())) {
            if (arguments[idx].equals(Type.getType(DroolsServiceType.class))) {
                if (overrideTypeJVMIndex >= 0) {
                    droolsGoalExecutionLog.getLogs().add(new DroolsGoalExecutionLog(
                            droolsGoalExecutionLog.getFileName(), droolsGoalExecutionLog.getAction(),
                            "Warning, @DroolsResourceType can't be used more than one time in the same constructor"));
                } else {
                    droolsGoalExecutionLog.getLogs()
                            .add(new DroolsGoalExecutionLog(droolsGoalExecutionLog.getFileName(),
                                    droolsGoalExecutionLog.getAction(),
                                    "This constructor will use resource Location override"));
                    overrideTypeJVMIndex = getJVMIndex(idx);
                }
            } else {
                droolsGoalExecutionLog.getLogs()
                        .add(new DroolsGoalExecutionLog(droolsGoalExecutionLog.getFileName(),
                                droolsGoalExecutionLog.getAction(),
                                "Warning, @DroolsResourceType must be used on DroolsServiceType parameter"));
            }
        }

        return super.visitParameterAnnotation(idx, name, arg2);
    }

    private String droolsName;

    private String droolsRule;

    private int getJVMIndex(int idx) {
        int jvmIdx = 1;
        for (int i = 0; i < idx; i++) {
            if (arguments[i].equals(Type.LONG_TYPE) || arguments[i].equals(Type.DOUBLE_TYPE))
                jvmIdx++;
            jvmIdx++;
        }
        return jvmIdx;
    }

    private Type arguments[];

    private DroolsGoalExecutionLog droolsGoalExecutionLog;

    private int overrideNameJVMIndex = -1;

    private int overrideTypeJVMIndex = -1;

    public DroolsAddConstructorMethodVisitor(MethodVisitor mv, int access, String name, String desc, String parent,
            String droolsName, String droolsRule, DroolsGoalExecutionLog droolsGoalExecutionLog) {
        super(mv, access, name, desc);
        this.parent = parent;
        this.droolsName = droolsName;
        this.droolsRule = droolsRule;
        arguments = Type.getArgumentTypes(desc);
        this.droolsGoalExecutionLog = droolsGoalExecutionLog;
    }

    /* (non-Javadoc)
     * @see org.objectweb.asm.commons.AdviceAdapter#onMethodEnter()
     */
    @Override
    protected void onMethodEnter() {
        this.visitVarInsn(Opcodes.ALOAD, 0);
        this.visitInsn(Opcodes.DUP);
        this.visitInsn(Opcodes.DUP);
        this.visitInsn(Opcodes.ICONST_0);
        this.visitFieldInsn(Opcodes.PUTFIELD, Type.getObjectType(parent).getInternalName(), droolsName,
                Type.BOOLEAN_TYPE.getDescriptor());
        this.visitTypeInsn(Opcodes.NEW, Type.getType(DroolsProvider.class).getInternalName());
        this.visitInsn(Opcodes.DUP);
        this.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getType(DroolsProvider.class).getInternalName(), "<init>",
                "()V");
        this.visitInsn(Opcodes.SWAP);
        this.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getObjectType(parent).getInternalName(), "getClass",
                "()Ljava/lang/Class;");
        if (overrideNameJVMIndex >= 0) {
            this.visitVarInsn(Opcodes.ALOAD, overrideNameJVMIndex);
        }
        if (overrideTypeJVMIndex >= 0) {
            this.visitVarInsn(Opcodes.ALOAD, overrideTypeJVMIndex);
        }
        if (overrideNameJVMIndex < 0 && overrideTypeJVMIndex < 0) {
            this.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getType(DroolsProvider.class).getInternalName(),
                    "getRuleBase", "(Ljava/lang/Class;)Lorg/drools/RuleBase;");
        } else if (overrideNameJVMIndex < 0 && overrideTypeJVMIndex >= 0) {
            this.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getType(DroolsProvider.class).getInternalName(),
                    "getRuleBaseOverride",
                    "(Ljava/lang/Class;Lorg/boretti/drools/integration/drools5/DroolsServiceType;)Lorg/drools/RuleBase;");
        } else if (overrideNameJVMIndex >= 0 && overrideTypeJVMIndex < 0) {
            this.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getType(DroolsProvider.class).getInternalName(),
                    "getRuleBaseOverride", "(Ljava/lang/Class;Ljava/lang/String;)Lorg/drools/RuleBase;");
        } else {
            this.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getType(DroolsProvider.class).getInternalName(),
                    "getRuleBaseOverride",
                    "(Ljava/lang/Class;Ljava/lang/String;Lorg/boretti/drools/integration/drools5/DroolsServiceType;)Lorg/drools/RuleBase;");
        }
        this.visitFieldInsn(Opcodes.PUTFIELD, Type.getObjectType(parent).getInternalName(), droolsRule,
                Type.getType(RuleBase.class).getDescriptor());
    }

    @Override
    public void visitMaxs(int maxStack, int maxLocals) {
        super.visitMaxs(maxStack + 6, maxLocals);
    }

}