Package org.jboss.byteman.rule.helper

Source Code of org.jboss.byteman.rule.helper.InterpretedHelper

/*
* JBoss, Home of Professional Open Source
* Copyright 2008-9, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
* @authors Andrew Dinn
*/
package org.jboss.byteman.rule.helper;

import org.jboss.byteman.rule.type.Type;
import org.jboss.byteman.rule.Rule;
import org.jboss.byteman.rule.exception.ExecuteException;
import org.jboss.byteman.rule.binding.Bindings;
import org.jboss.byteman.rule.binding.Binding;
import org.jboss.byteman.agent.Transformer;

import java.util.HashMap;
import java.util.Iterator;

/**
* Implementation of RuleHelper which extends the functionality of the standard helper class,
* Helper, by adding the methods required to implement interface RuleHelper. It provides an
* implementation which executes rules by interpreting the rule tree. Any rule which employs the
* standard helper type checks built in method calls against class Helper. However, the interpreter
* assumes that the helper object implements InterpretedHelper.
*
* When a rule is compiled class Helper is extended with a generated class CompiledHelper<NNN>
* which also implements interface RuleHelper. The implementation of the execute method is generated
* by translating the parse tree to bytecode. Builtin calls are translated to calls of methods
* defined by class Helper.
*
* A rule can also specify its own helper class in order to provide its own set of builtin
* operations. The helper class does not implement interface RuleHelper. Instead the
* compilation process will generate a subclass of the user-defined helper class which
* provides an appropriate implementation for the RuleHelper methods, including an implementation
* of the execute method dreived from the rule parse tree. As in the default case, builtin calls
* are translated to calls of methods defined by the helper class.
*/
public class InterpretedHelper extends Helper implements HelperAdapter
{
    protected HashMap<String, Object> bindingMap;

    public InterpretedHelper(Rule rule)
    {
        super(rule);
        bindingMap = new HashMap<String, Object>();
    }

    /**
     * install values into the bindings map and then call the execute0 method
     * to actually execute the rule
     * @param recipient
     * @param args
     */
    public void execute(Object recipient, Object[] args)
            throws ExecuteException
    {
        if (Transformer.isVerbose()) {
            System.out.println(rule.getName() + " execute");
        }
        Bindings bindings = rule.getBindings();
        Iterator<Binding> iterator = bindings.iterator();
        while (iterator.hasNext()) {
            Binding binding = iterator.next();
            String name = binding.getName();
            if (binding.isAlias()) {
                // this is a local var used to refer to a method recipient or parameter
                // so use the value and type associated with the alias
                binding = binding.getAlias();
            }
            if (binding.isHelper()) {
                bindingMap.put(name, this);
            } else if (binding.isRecipient()) {
                bindingMap.put(name, recipient);
            // } else if (!binding.isParam() || binding.isLocalVar() || binding.isReturn() ||
            //         binding.isThrowable() || binding.isParamCount() || binding.isParamArray()) {
            } else if (!binding.isBindVar()) {
                bindingMap.put(name, args[binding.getCallArrayIndex()]);
            }
        }

        // now do the actual execution

        execute0();

        // now restore update bindings

        iterator = bindings.iterator();

        while (iterator.hasNext()) {
            Binding binding = iterator.next();
            String name = binding.getName();
            if (binding.isAlias()) {
                binding = binding.getAlias();
            }

            if (binding.isUpdated()) {
                // if (binding.isParam() || binding.isLocalVar() || binding.isReturn()) {
                if (!binding.isBindVar()) {
                    Object value = bindingMap.get(name);
                    int idx = binding.getCallArrayIndex();
                    args[idx] = value;
                }
            }
        }

    }

    /**
     * basic implementation of rule execution
     *
     * @throws ExecuteException
     */
       
    protected void execute0()
            throws ExecuteException
    {
        // System.out.println(rule.getName() + " execute0");
        bind();
        if (test()) {
            fire();
        }
    }

    public void setBinding(String name, Object value)
    {
        bindingMap.put(name, value);
    }

    public Object getBinding(String name)
    {
        return bindingMap.get(name);
    }

    private void bind()
            throws ExecuteException
    {
        // System.out.println(rule.getName() + " bind");
        rule.getEvent().interpret(this);
    }

    private boolean test()
            throws ExecuteException
    {
        // System.out.println(rule.getName() + " test");
        return (Boolean)rule.getCondition().interpret(this);
    }
       
    private void fire()
            throws ExecuteException
    {
        // System.out.println(rule.getName() + " fire");
        rule.getAction().interpret(this);
    }

    public String getName() {
        return rule.getName();
    }

    public Object getAccessibleField(Object owner, int fieldIndex)
    {
        return rule.getAccessibleField(owner, fieldIndex);
    }

    public void setAccessibleField(Object owner, Object value, int fieldIndex)
    {
        rule.setAccessibleField(owner, value, fieldIndex);
    }
    public Object invokeAccessibleMethod(Object target, Object[] args, int methodIndex)
    {
        return rule.invokeAccessibleMethod(target, args, methodIndex);
    }
}
TOP

Related Classes of org.jboss.byteman.rule.helper.InterpretedHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.