package railo.transformer.cfml.evaluator.impl; import java.util.Iterator; import java.util.List; import java.util.Map; import railo.commons.lang.StringUtil; import railo.runtime.functions.system.CFFunction; import railo.runtime.listener.AppListenerUtil; import railo.transformer.bytecode.Body; import railo.transformer.bytecode.BytecodeException; import railo.transformer.bytecode.Literal; import railo.transformer.bytecode.Statement; import railo.transformer.bytecode.cast.CastBoolean; import railo.transformer.bytecode.cast.CastString; import railo.transformer.bytecode.expression.ExprString; import railo.transformer.bytecode.expression.Expression; import railo.transformer.bytecode.literal.LitBoolean; import railo.transformer.bytecode.literal.LitLong; import railo.transformer.bytecode.literal.LitString; import railo.transformer.bytecode.statement.tag.Attribute; import railo.transformer.bytecode.statement.tag.Tag; import railo.transformer.bytecode.util.ASMUtil; import railo.transformer.cfml.evaluator.EvaluatorException; import railo.transformer.cfml.evaluator.EvaluatorSupport; import railo.transformer.library.function.FunctionLib; import railo.transformer.library.function.FunctionLibFunction; import railo.transformer.library.tag.TagLibTag; /** * Prueft den Kontext des Tag function. * Das Attribute <code>argument</code> darf nur direkt innerhalb des Tag <code>function</code> liegen. * Dem Tag <code>argument</code> muss als erstes im tag function vorkommen */ public final class Function extends EvaluatorSupport { //� /** * @see railo.transformer.cfml.evaluator.EvaluatorSupport#evaluate(org.w3c.dom.Element, railo.transformer.library.tag.TagLibTag) */ public void evaluate(Tag tag, TagLibTag libTag, FunctionLib[] flibs) throws EvaluatorException { //Body p=(Body) tag.getParent(); //Statement pp = p.getParent(); boolean isCFC=true; try { isCFC = ASMUtil.getAncestorPage(tag).isComponent(); } catch (BytecodeException e) {} Attribute attrName = tag.getAttribute("name"); if(attrName!=null) { Expression expr = attrName.getValue(); if(expr instanceof LitString && !isCFC){ checkFunctionName(((LitString)expr).getString(),flibs); } } // attribute modifier Attribute attrModifier = tag.getAttribute("modifier"); if(attrModifier!=null) { ExprString expr = CastString.toExprString(attrModifier.getValue()); if(!(expr instanceof Literal)) throw new EvaluatorException("Attribute modifier of the Tag Function, must be one of the following literal string values: [abstract] or [final]"); String modifier=StringUtil.emptyIfNull(((Literal)expr).getString()).trim(); if(!StringUtil.isEmpty(modifier) && !"abstract".equalsIgnoreCase(modifier) && !"final".equalsIgnoreCase(modifier)) throw new EvaluatorException("Attribute modifier of the Tag Function, must be one of the following literal string values: [abstract] or [final]"); boolean abstr = "abstract".equalsIgnoreCase(modifier); if(abstr)throwIfNotEmpty(tag); } // cachedWithin Attribute attrCachedWithin = tag.getAttribute("cachedwithin"); if(attrCachedWithin!=null) { Expression val = attrCachedWithin.getValue(); tag.addAttribute(new Attribute(attrCachedWithin.isDynamicType(), attrCachedWithin.getName(), LitLong.toExpr(ASMUtil.timeSpanToLong(val), null, null), "numeric")); } // Attribute localMode Attribute attrLocalMode = tag.getAttribute("localmode"); if(attrLocalMode!=null) { Expression expr = attrLocalMode.getValue(); String str = ASMUtil.toString(expr,null); if(!StringUtil.isEmpty(str) && AppListenerUtil.toLocalMode(str, -1)==-1) throw new EvaluatorException("Attribute localMode of the Tag Function, must be a literal value (modern, classic, true or false)"); //boolean output = ((LitBoolean)expr).getBooleanValue(); //if(!output) ASMUtil.removeLiterlChildren(tag, true); } // Attribute Output // "output=true" wird in "railo.transformer.cfml.attributes.impl.Function" geh�ndelt Attribute attrOutput = tag.getAttribute("output"); if(attrOutput!=null) { Expression expr = CastBoolean.toExprBoolean(attrOutput.getValue()); if(!(expr instanceof LitBoolean)) throw new EvaluatorException("Attribute output of the Tag Function, must be a literal boolean value (true or false, yes or no)"); //boolean output = ((LitBoolean)expr).getBooleanValue(); //if(!output) ASMUtil.removeLiterlChildren(tag, true); } Attribute attrBufferOutput = tag.getAttribute("bufferoutput"); if(attrBufferOutput!=null) { Expression expr = CastBoolean.toExprBoolean(attrBufferOutput.getValue()); if(!(expr instanceof LitBoolean)) throw new EvaluatorException("Attribute bufferOutput of the Tag Function, must be a literal boolean value (true or false, yes or no)"); //boolean output = ((LitBoolean)expr).getBooleanValue(); //if(!output) ASMUtil.removeLiterlChildren(tag, true); } //if(ASMUtil.isRoot(pp)) { Map attrs = tag.getAttributes(); Iterator it = attrs.keySet().iterator(); Attribute attr; while(it.hasNext()) { attr=(Attribute) attrs.get(it.next()); checkAttributeValue(tag,attr); } //} } public static void checkFunctionName(String name, FunctionLib[] flibs) throws EvaluatorException { FunctionLibFunction flf; for (int i = 0; i < flibs.length; i++) { flf = flibs[i].getFunction(name); if(flf!=null && flf.getClazz()!=CFFunction.class) { throw new EvaluatorException("The name ["+name+"] is already used by a built in Function"); } } } public static void throwIfNotEmpty(Tag tag) throws EvaluatorException { Body body = tag.getBody(); List<Statement> statments = body.getStatements(); Statement stat; Iterator<Statement> it = statments.iterator(); TagLibTag tlt; while(it.hasNext()) { stat=it.next(); if(stat instanceof Tag) { tlt = ((Tag)stat).getTagLibTag(); if(!tlt.getTagClassName().equals("railo.runtime.tag.Argument")) throw new EvaluatorException("tag "+tlt.getFullName()+" is not allowed inside a function declaration"); } /*else if(stat instanceof PrintOut) { //body.remove(stat); }*/ } } private void checkAttributeValue(Tag tag, Attribute attr) throws EvaluatorException { if(!(attr.getValue() instanceof Literal)) throw new EvaluatorException("Attribute ["+attr.getName()+"] of the Tag ["+tag.getFullname()+"] must be a literal/constant value"); } }