001 package railo.transformer.cfml.evaluator.impl; 002 003 004 import java.util.Iterator; 005 import java.util.List; 006 import java.util.Map; 007 008 import railo.commons.lang.StringUtil; 009 import railo.runtime.functions.system.CFFunction; 010 import railo.runtime.listener.AppListenerUtil; 011 import railo.transformer.bytecode.Body; 012 import railo.transformer.bytecode.BytecodeException; 013 import railo.transformer.bytecode.Literal; 014 import railo.transformer.bytecode.Statement; 015 import railo.transformer.bytecode.cast.CastBoolean; 016 import railo.transformer.bytecode.cast.CastString; 017 import railo.transformer.bytecode.expression.ExprString; 018 import railo.transformer.bytecode.expression.Expression; 019 import railo.transformer.bytecode.literal.LitBoolean; 020 import railo.transformer.bytecode.literal.LitLong; 021 import railo.transformer.bytecode.literal.LitString; 022 import railo.transformer.bytecode.statement.tag.Attribute; 023 import railo.transformer.bytecode.statement.tag.Tag; 024 import railo.transformer.bytecode.util.ASMUtil; 025 import railo.transformer.cfml.evaluator.EvaluatorException; 026 import railo.transformer.cfml.evaluator.EvaluatorSupport; 027 import railo.transformer.library.function.FunctionLib; 028 import railo.transformer.library.function.FunctionLibFunction; 029 import railo.transformer.library.tag.TagLibTag; 030 031 /** 032 * Prueft den Kontext des Tag function. 033 * Das Attribute <code>argument</code> darf nur direkt innerhalb des Tag <code>function</code> liegen. 034 * Dem Tag <code>argument</code> muss als erstes im tag function vorkommen 035 */ 036 public final class Function extends EvaluatorSupport { 037 038 //� 039 /** 040 * @see railo.transformer.cfml.evaluator.EvaluatorSupport#evaluate(org.w3c.dom.Element, railo.transformer.library.tag.TagLibTag) 041 */ 042 public void evaluate(Tag tag, TagLibTag libTag, FunctionLib[] flibs) throws EvaluatorException { 043 //Body p=(Body) tag.getParent(); 044 //Statement pp = p.getParent(); 045 046 boolean isCFC=true; 047 try { 048 isCFC = ASMUtil.getAncestorPage(tag).isComponent(); 049 } catch (BytecodeException e) {} 050 051 Attribute attrName = tag.getAttribute("name"); 052 if(attrName!=null) { 053 Expression expr = attrName.getValue(); 054 if(expr instanceof LitString && !isCFC){ 055 checkFunctionName(((LitString)expr).getString(),flibs); 056 } 057 058 } 059 // attribute modifier 060 Attribute attrModifier = tag.getAttribute("modifier"); 061 if(attrModifier!=null) { 062 ExprString expr = CastString.toExprString(attrModifier.getValue()); 063 if(!(expr instanceof Literal)) 064 throw new EvaluatorException("Attribute modifier of the Tag Function, must be one of the following literal string values: [abstract] or [final]"); 065 String modifier=StringUtil.emptyIfNull(((Literal)expr).getString()).trim(); 066 if(!StringUtil.isEmpty(modifier) && !"abstract".equalsIgnoreCase(modifier) && !"final".equalsIgnoreCase(modifier)) 067 throw new EvaluatorException("Attribute modifier of the Tag Function, must be one of the following literal string values: [abstract] or [final]"); 068 069 070 boolean abstr = "abstract".equalsIgnoreCase(modifier); 071 if(abstr)throwIfNotEmpty(tag); 072 } 073 074 // cachedWithin 075 Attribute attrCachedWithin = tag.getAttribute("cachedwithin"); 076 if(attrCachedWithin!=null) { 077 Expression val = attrCachedWithin.getValue(); 078 tag.addAttribute(new Attribute(attrCachedWithin.isDynamicType(), attrCachedWithin.getName(), LitLong.toExpr(ASMUtil.timeSpanToLong(val), null, null), "numeric")); 079 } 080 081 // Attribute localMode 082 Attribute attrLocalMode = tag.getAttribute("localmode"); 083 if(attrLocalMode!=null) { 084 Expression expr = attrLocalMode.getValue(); 085 String str = ASMUtil.toString(expr,null); 086 if(!StringUtil.isEmpty(str) && AppListenerUtil.toLocalMode(str, -1)==-1) 087 throw new EvaluatorException("Attribute localMode of the Tag Function, must be a literal value (modern, classic, true or false)"); 088 //boolean output = ((LitBoolean)expr).getBooleanValue(); 089 //if(!output) ASMUtil.removeLiterlChildren(tag, true); 090 } 091 092 093 // Attribute Output 094 // "output=true" wird in "railo.transformer.cfml.attributes.impl.Function" geh�ndelt 095 Attribute attrOutput = tag.getAttribute("output"); 096 if(attrOutput!=null) { 097 Expression expr = CastBoolean.toExprBoolean(attrOutput.getValue()); 098 if(!(expr instanceof LitBoolean)) 099 throw new EvaluatorException("Attribute output of the Tag Function, must be a literal boolean value (true or false, yes or no)"); 100 //boolean output = ((LitBoolean)expr).getBooleanValue(); 101 //if(!output) ASMUtil.removeLiterlChildren(tag, true); 102 } 103 104 Attribute attrBufferOutput = tag.getAttribute("bufferoutput"); 105 if(attrBufferOutput!=null) { 106 Expression expr = CastBoolean.toExprBoolean(attrBufferOutput.getValue()); 107 if(!(expr instanceof LitBoolean)) 108 throw new EvaluatorException("Attribute bufferOutput of the Tag Function, must be a literal boolean value (true or false, yes or no)"); 109 //boolean output = ((LitBoolean)expr).getBooleanValue(); 110 //if(!output) ASMUtil.removeLiterlChildren(tag, true); 111 } 112 113 114 //if(ASMUtil.isRoot(pp)) { 115 Map attrs = tag.getAttributes(); 116 Iterator it = attrs.keySet().iterator(); 117 Attribute attr; 118 while(it.hasNext()) { 119 attr=(Attribute) attrs.get(it.next()); 120 checkAttributeValue(tag,attr); 121 } 122 //} 123 124 } 125 126 public static void checkFunctionName(String name, FunctionLib[] flibs) throws EvaluatorException { 127 FunctionLibFunction flf; 128 for (int i = 0; i < flibs.length; i++) { 129 flf = flibs[i].getFunction(name); 130 if(flf!=null && flf.getClazz()!=CFFunction.class) { 131 throw new EvaluatorException("The name ["+name+"] is already used by a built in Function"); 132 } 133 } 134 } 135 136 public static void throwIfNotEmpty(Tag tag) throws EvaluatorException { 137 Body body = tag.getBody(); 138 List<Statement> statments = body.getStatements(); 139 Statement stat; 140 Iterator<Statement> it = statments.iterator(); 141 TagLibTag tlt; 142 143 while(it.hasNext()) { 144 stat=it.next(); 145 if(stat instanceof Tag) { 146 tlt = ((Tag)stat).getTagLibTag(); 147 if(!tlt.getTagClassName().equals("railo.runtime.tag.Argument")) 148 throw new EvaluatorException("tag "+tlt.getFullName()+" is not allowed inside a function declaration"); 149 } 150 /*else if(stat instanceof PrintOut) { 151 //body.remove(stat); 152 }*/ 153 } 154 } 155 156 private void checkAttributeValue(Tag tag, Attribute attr) throws EvaluatorException { 157 if(!(attr.getValue() instanceof Literal)) 158 throw new EvaluatorException("Attribute ["+attr.getName()+"] of the Tag ["+tag.getFullname()+"] must be a literal/constant value"); 159 160 } 161 }