/*
* JBoss, Home of Professional Open Source
* Copyright 2008-10 Red Hat 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;
import org.jboss.byteman.rule.compiler.CompileContext;
import org.jboss.byteman.rule.type.Type;
import org.jboss.byteman.rule.expression.ExpressionHelper;
import org.jboss.byteman.rule.expression.Expression;
import org.jboss.byteman.rule.grammar.ECATokenLexer;
import org.jboss.byteman.rule.grammar.ECAGrammarParser;
import org.jboss.byteman.rule.grammar.ParseNode;
import org.jboss.byteman.rule.exception.ParseException;
import org.jboss.byteman.rule.exception.TypeException;
import org.jboss.byteman.rule.exception.ExecuteException;
import org.jboss.byteman.rule.exception.CompileException;
import org.jboss.byteman.rule.helper.HelperAdapter;
import org.objectweb.asm.MethodVisitor;
import java.io.StringWriter;
import java.io.StringReader;
import java_cup.runtime.Symbol;
/**
* class which represents a rule condition comprising a boolean expression
*/
public class Condition extends RuleElement
{
public static Condition create(Rule rule, ParseNode conditionTree) throws TypeException
{
Condition condition = new Condition(rule, conditionTree);
return condition;
}
public static Condition create(Rule rule, String text) throws ParseException, TypeException
{
if ("".equals(text)) {
return new Condition(rule);
}
String fulltext = "BIND NOTHING IF \n" + text + "\n DO NOTHING";
try {
ECATokenLexer lexer = new ECATokenLexer(new StringReader(text));
ECAGrammarParser parser = new ECAGrammarParser(lexer);
Symbol condition_parse = parser.parse();
ParseNode conditionTree = (ParseNode) condition_parse.value;
Condition condition = new Condition(rule, conditionTree);
return condition;
} catch (Exception e) {
throw new ParseException("org.jboss.byteman.rule.Condition : error parsing condition\n" + text, e);
}
}
protected Condition(Rule rule, ParseNode conditionTree)
throws TypeException
{
super(rule);
int tag = conditionTree.getTag();
condition = ExpressionHelper.createExpression(rule, rule.getBindings(), conditionTree, Type.BOOLEAN);
// check bindings
condition.bind();
}
protected Condition(Rule rule)
{
super(rule);
this.condition = null;
}
public Type typeCheck(Type expected) throws TypeException {
// expected must be Type.Z
if (condition != null) {
condition.typeCheck(Type.Z);
}
return Type.Z;
}
public void compile(MethodVisitor mv, CompileContext compileContext) throws CompileException {
int currentStack = compileContext.getStackCount();
// get the condition to compile itself -- it adds 1 to stack height
condition.compile(mv, compileContext);
// unbox if necessary
if (condition.getType() == Type.BOOLEAN) {
compileUnbox(Type.BOOLEAN, Type.Z, mv, compileContext);
}
// check stack heights
if (compileContext.getStackCount() != currentStack + 1) {
throw new CompileException("Condition.compile : invalid stack height " + compileContext.getStackCount() + " expecting " + currentStack);
}
}
public Object interpret(HelperAdapter helper)
throws ExecuteException
{
Boolean result = (Boolean)condition.interpret(helper);
return result;
}
public void writeTo(StringWriter stringWriter)
{
if (condition == null) {
stringWriter.write("IF TRUE");
} else {
stringWriter.write("IF ");
condition.writeTo(stringWriter);
}
stringWriter.write("\n");
}
private Expression condition;
}