/** * * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. * * This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>. * **/ package lucee.transformer.bytecode.statement.tag; import lucee.commons.lang.StringUtil; import lucee.runtime.PageContext; import lucee.runtime.config.NullSupportHelper; import lucee.runtime.exp.ExpressionException; import lucee.runtime.exp.PageException; import lucee.runtime.interpreter.VariableInterpreter; import lucee.transformer.Factory; import lucee.transformer.Position; import lucee.transformer.TransformerException; import lucee.transformer.bytecode.BytecodeContext; import lucee.transformer.bytecode.util.ASMConstants; import lucee.transformer.bytecode.util.Types; import lucee.transformer.cfml.evaluator.impl.Argument; import lucee.transformer.expression.Expression; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.GeneratorAdapter; import org.objectweb.asm.commons.Method; public final class TagParam extends TagBaseNoFinal { // public static final Type NULL_SUPPORT_HELPER = Type.getType(NullSupportHelper.class); public static final Type VARIABLE_INTERPRETER = Type.getType(VariableInterpreter.class); // void param(String type, String name, Object defaultValue) private static final Method PARAM_TYPE_NAME_DEFAULTVALUE = new Method( "param", Types.VOID, new Type[]{Types.STRING,Types.STRING,Types.OBJECT} ); private static final Method PARAM_TYPE_NAME_DEFAULTVALUE_REGEX = new Method( "param", Types.VOID, new Type[]{Types.STRING,Types.STRING,Types.OBJECT,Types.STRING} ); private static final Method PARAM_TYPE_NAME_DEFAULTVALUE_MIN_MAX = new Method( "param", Types.VOID, new Type[]{Types.STRING,Types.STRING,Types.OBJECT,Types.DOUBLE_VALUE,Types.DOUBLE_VALUE} ); private static final Method PARAM_TYPE_NAME_DEFAULTVALUE_MAXLENGTH = new Method( "param", Types.VOID, new Type[]{Types.STRING,Types.STRING,Types.OBJECT,Types.INT_VALUE} ); private static final Method IS_EMPTY = new Method( "isEmpty", Types.BOOLEAN_VALUE, new Type[]{Types.STRING} ); private static final Method CONSTR_STRING = new Method( "<init>", Types.VOID, new Type[]{Types.STRING}// ); private static final Method NULL = new Method( "NULL", Types.OBJECT, new Type[]{Types.PAGE_CONTEXT}// ); private static final Method GET_VARIABLE_EL = new Method( "getVariableEL", Types.OBJECT, new Type[]{Types.PAGE_CONTEXT,Types.STRING,Types.OBJECT}// ); private static final Method APPEND_OBJECT = new Method( "append", Types.STRING_BUILDER, new Type[]{Types.OBJECT} ); private static final Method APPEND_STRING = new Method( "append", Types.STRING_BUILDER, new Type[]{Types.STRING} ); private static final Method TO_STRING = new Method( "toString", Types.STRING, new Type[]{} ); private static final Method SUB_PARAM = new Method( "subparam", Types.VOID, new Type[]{Types.STRING,Types.STRING,Types.OBJECT,Types.DOUBLE_VALUE,Types.DOUBLE_VALUE ,Types.STRING,Types.INT_VALUE,Types.BOOLEAN_VALUE} ); private static final Method T = new Method( "t", Types.VOID, new Type[]{Types.STRING,Types.STRING,Types.OBJECT,Types.DOUBLE_VALUE,Types.DOUBLE_VALUE } ); public TagParam(Factory f, Position start,Position end) { super(f,start,end); } private double t(PageContext pc) throws ExpressionException { //if(StringUtil.isEmpty(name)) throw new ExpressionException("The attribute name is required"); //String name="kkk"; //Object value=VariableInterpreter.getVariableEL(pc,name,NullSupportHelper.NULL(pc)); /*Object value=null; Object defaultValue=null; boolean isNew=false; if(NullSupportHelper.NULL(pc)==value) { if(defaultValue==null) throw new ExpressionException("The required parameter ["+name+"] was not provided."); value=defaultValue; isNew=true; }*/ return Double.NaN; } @Override public void _writeOut(BytecodeContext bc) throws TransformerException { GeneratorAdapter adapter = bc.getAdapter(); Argument.checkDefaultValue(this); // attributes Expression name=getAttribute("name").getValue(); Attribute attrDefault = getAttribute("default"); Expression def=null; if(attrDefault!=null) def=attrDefault.getValue();// .writeOut(bc, Expression.MODE_REF); //else adapter.visitInsn(Opcodes.ACONST_NULL); // check attributes name // if(StringUtil.isEmpty(name)) throw new ExpressionException("The attribute name is required"); /*name.writeOut(bc, Expression.MODE_REF); adapter.invokeStatic(Types.STRING_UTIL, IS_EMPTY); Label end = new Label(); adapter.visitJumpInsn(Opcodes.IFEQ, end); //adapter.visitLabel(new Label()); adapter.newInstance(Types.EXPRESSION_EXCEPTION); adapter.dup(); adapter.push("for param a name is required"); adapter.invokeConstructor(Types.EXPRESSION_EXCEPTION, CONSTR_STRING); adapter.throwException(); adapter.visitLabel(end);*/ // value // Object value=VariableInterpreter.getVariableEL(this,name,NullSupportHelper.NULL(this)); int value = adapter.newLocal(Types.OBJECT); adapter.loadArg(0); // pc name.writeOut(bc, Expression.MODE_REF);// name adapter.loadArg(0); // pc adapter.invokeStatic(NULL_SUPPORT_HELPER, NULL); adapter.invokeStatic(VARIABLE_INTERPRETER, GET_VARIABLE_EL); adapter.storeLocal(value); // check value 2=value; 3=defaultValue; isNew=4 int isNew = adapter.newLocal(Types.BOOLEAN_VALUE); adapter.push(false); adapter.storeLocal(isNew, Types.BOOLEAN_VALUE); //Label l3 = new Label(); //mv.visitLabel(l3); adapter.loadArg(0); adapter.invokeStatic(NULL_SUPPORT_HELPER, NULL); adapter.loadLocal(value); Label l4 = new Label(); adapter.visitJumpInsn(Opcodes.IF_ACMPNE, l4); Label l5 = new Label(); adapter.visitLabel(l5); if(def!=null) def.writeOut(bc, Expression.MODE_REF); else ASMConstants.NULL(adapter); adapter.dup(); int ldef = adapter.newLocal(Types.OBJECT); adapter.storeLocal(ldef); Label l6 = new Label(); adapter.visitJumpInsn(Opcodes.IFNONNULL, l6); Label l7 = new Label(); adapter.visitLabel(l7); adapter.newInstance(Types.EXPRESSION_EXCEPTION); adapter.dup(); adapter.newInstance(Types.STRING_BUILDER); adapter.dup(); adapter.push("The required parameter ["); adapter.invokeConstructor(Types.STRING_BUILDER, CONSTR_STRING); name.writeOut(bc, Expression.MODE_REF); adapter.invokeVirtual(Types.STRING_BUILDER, APPEND_OBJECT); adapter.visitLdcInsn("] was not provided."); adapter.invokeVirtual(Types.STRING_BUILDER, APPEND_STRING); adapter.invokeVirtual(Types.STRING_BUILDER, TO_STRING); adapter.invokeConstructor(Types.EXPRESSION_EXCEPTION, CONSTR_STRING); adapter.throwException(); adapter.visitLabel(l6); adapter.loadLocal(ldef); adapter.storeLocal(value); adapter.push(true); adapter.storeLocal(isNew); adapter.visitLabel(l4); // pc adapter.loadArg(0); adapter.checkCast(Types.PAGE_CONTEXT_IMPL); // type Attribute attrType = getAttribute("type"); if(attrType!=null) attrType.getValue().writeOut(bc, Expression.MODE_REF); else adapter.push("any"); //adapter.push("any"); // name name.writeOut(bc, Expression.MODE_REF); //adapter.push("url.test"); // value adapter.loadLocal(value); Attribute attrMin = getAttribute("min"); Attribute attrMax = getAttribute("max"); Attribute attrPattern = getAttribute("pattern"); Attribute maxLength = getAttribute("maxLength"); // min/max if(attrMin!=null || attrMax!=null) { // min if(attrMin!=null) attrMin.getValue().writeOut(bc, Expression.MODE_VALUE); else adapter.visitLdcInsn(new Double("NaN")); // max if(attrMax!=null)attrMax.getValue().writeOut(bc, Expression.MODE_VALUE); else adapter.visitLdcInsn(new Double("NaN")); } else { adapter.visitLdcInsn(new Double("NaN")); adapter.visitLdcInsn(new Double("NaN")); } //adapter.push(-1); //adapter.push(-1); //adapter.invokeVirtual(Types.PAGE_CONTEXT_IMPL, T); //if(true)return; // pattern if(attrPattern!=null) attrPattern.getValue().writeOut(bc, Expression.MODE_REF); else ASMConstants.NULL(adapter); //ASMConstants.NULL(adapter); // maxlength if(maxLength!=null) bc.getFactory().toExprInt(maxLength.getValue()).writeOut(bc, Expression.MODE_VALUE); else adapter.push(-1); //adapter.push(-1); // isNew adapter.loadLocal(isNew,Types.BOOLEAN_VALUE); //adapter.push(true); // subparam adapter.invokeVirtual(Types.PAGE_CONTEXT_IMPL, SUB_PARAM); // param(type, name, defaultValue,Double.NaN,Double.NaN,regex,-1); // subparam(type, name, value, min, max, strPattern, maxLength, isNew); // SSO } }