001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019/** 020 * Implements the CFML Function getfunctiondescription 021 */ 022package lucee.runtime.functions.other; 023 024import java.util.ArrayList; 025 026import lucee.commons.lang.CFTypes; 027import lucee.commons.lang.ExceptionUtil; 028import lucee.commons.lang.StringUtil; 029import lucee.runtime.PageContext; 030import lucee.runtime.config.ConfigImpl; 031import lucee.runtime.exp.ExpressionException; 032import lucee.runtime.exp.PageException; 033import lucee.runtime.ext.function.Function; 034import lucee.runtime.functions.system.CFFunction; 035import lucee.runtime.op.Caster; 036import lucee.runtime.type.Array; 037import lucee.runtime.type.ArrayImpl; 038import lucee.runtime.type.Collection; 039import lucee.runtime.type.Collection.Key; 040import lucee.runtime.type.FunctionArgument; 041import lucee.runtime.type.KeyImpl; 042import lucee.runtime.type.Struct; 043import lucee.runtime.type.StructImpl; 044import lucee.runtime.type.UDF; 045import lucee.runtime.type.util.ArrayUtil; 046import lucee.runtime.type.util.KeyConstants; 047import lucee.transformer.library.function.FunctionLib; 048import lucee.transformer.library.function.FunctionLibFunction; 049import lucee.transformer.library.function.FunctionLibFunctionArg; 050import lucee.transformer.library.tag.TagLibFactory; 051 052public final class GetFunctionData implements Function { 053 private static final Collection.Key SOURCE = KeyConstants._source; 054 private static final Collection.Key RETURN_TYPE = KeyImpl.intern("returnType"); 055 private static final Collection.Key ARGUMENT_TYPE = KeyImpl.intern("argumentType"); 056 private static final Collection.Key ARG_MIN = KeyImpl.intern("argMin"); 057 private static final Collection.Key ARG_MAX = KeyImpl.intern("argMax"); 058 059 public static Struct call(PageContext pc , String strFunctionName) throws PageException { 060 FunctionLib[] flds; 061 flds = ((ConfigImpl)pc.getConfig()).getFLDs(); 062 063 064 FunctionLibFunction function=null; 065 for(int i=0;i<flds.length;i++) { 066 function = flds[i].getFunction(strFunctionName.toLowerCase()); 067 if(function!=null)break; 068 } 069 if(function == null) throw new ExpressionException("function ["+strFunctionName+"] is not a built in function"); 070 071 //sct.set("returnTypeClass",_class(function.getCazz())); 072 //sct.set("class",__class(function.getCazz())); 073 074 075 076 // CFML Based Function 077 Class clazz=null; 078 try{ 079 clazz=function.getClazz(); 080 } 081 catch(Throwable t){ 082 ExceptionUtil.rethrowIfNecessary(t); 083 } 084 if(clazz==lucee.runtime.functions.system.CFFunction.class){ 085 return cfmlBasedFunction(pc,function); 086 } 087 return javaBasedFunction(function); 088 089 090 091 } 092 093 private static Struct javaBasedFunction(FunctionLibFunction function) throws PageException { 094 Struct sct=new StructImpl(); 095 sct.set(KeyConstants._name,function.getName()); 096 sct.set(KeyConstants._status,TagLibFactory.toStatus(function.getStatus())); 097 sct.set(KeyConstants._description,StringUtil.emptyIfNull(function.getDescription())); 098 if(!ArrayUtil.isEmpty(function.getKeywords()))sct.set("keywords",Caster.toArray(function.getKeywords())); 099 100 101 sct.set(RETURN_TYPE,StringUtil.emptyIfNull(function.getReturnTypeAsString())); 102 sct.set(ARGUMENT_TYPE,StringUtil.emptyIfNull(function.getArgTypeAsString())); 103 sct.set(ARG_MIN,Caster.toDouble(function.getArgMin())); 104 sct.set(ARG_MAX,Caster.toDouble(function.getArgMax())); 105 sct.set(KeyConstants._type,"java"); 106 String[] names = function.getMemberNames(); 107 if(!ArrayUtil.isEmpty(names) && function.getMemberType()!=CFTypes.TYPE_UNKNOW) { 108 StructImpl mem = new StructImpl(); 109 sct.set(KeyConstants._member, mem); 110 mem.set(KeyConstants._name,names[0]); 111 mem.set(KeyConstants._chaining,Caster.toBoolean(function.getMemberChaining())); 112 mem.set(KeyConstants._type, function.getMemberTypeAsString()); 113 mem.set("position", Caster.toDouble(function.getMemberPosition())); 114 } 115 116 Array _args=new ArrayImpl(); 117 sct.set(KeyConstants._arguments,_args); 118 if(function.getArgType()!=FunctionLibFunction.ARG_DYNAMIC){ 119 ArrayList<FunctionLibFunctionArg> args = function.getArg(); 120 for(int i=0;i<args.size();i++) { 121 FunctionLibFunctionArg arg=args.get(i); 122 Struct _arg=new StructImpl(); 123 _arg.set(KeyConstants._required,arg.getRequired()?Boolean.TRUE:Boolean.FALSE); 124 _arg.set(KeyConstants._type,StringUtil.emptyIfNull(arg.getTypeAsString())); 125 _arg.set(KeyConstants._name,StringUtil.emptyIfNull(arg.getName())); 126 _arg.set(KeyConstants._status,TagLibFactory.toStatus(arg.getStatus())); 127 _arg.set("defaultValue",arg.getDefaultValue()); 128 _arg.set(KeyConstants._description,StringUtil.toStringEmptyIfNull(arg.getDescription())); 129 130 131 _args.append(_arg); 132 } 133 } 134 return sct; 135 } 136 137 private static Struct cfmlBasedFunction(PageContext pc, FunctionLibFunction function) throws PageException { 138 Struct sct=new StructImpl(); 139 ArrayList<FunctionLibFunctionArg> args = function.getArg(); 140 141 String filename = Caster.toString(args.get(0).getDefaultValue()); 142 Key name = KeyImpl.toKey(args.get(1).getDefaultValue()); 143 boolean isWeb = Caster.toBooleanValue(args.get(2).getDefaultValue()); 144 UDF udf = CFFunction.loadUDF(pc, filename, name, isWeb); 145 146 sct.set(KeyConstants._name,function.getName()); 147 sct.set(ARGUMENT_TYPE,"fixed"); 148 sct.set(KeyConstants._description,StringUtil.emptyIfNull(udf.getHint())); 149 sct.set(RETURN_TYPE,StringUtil.emptyIfNull(udf.getReturnTypeAsString())); 150 sct.set(KeyConstants._type,"cfml"); 151 sct.set(SOURCE,udf.getPageSource().getDisplayPath()); 152 sct.set(KeyConstants._status,"implemeted"); 153 154 155 FunctionArgument[] fas = udf.getFunctionArguments(); 156 Array _args=new ArrayImpl(); 157 sct.set(KeyConstants._arguments,_args); 158 int min=0,max=0; 159 for(int i=0;i<fas.length;i++) { 160 FunctionArgument fa=fas[i]; 161 Struct meta = fa.getMetaData(); 162 163 Struct _arg=new StructImpl(); 164 if(fa.isRequired()) min++; 165 max++; 166 _arg.set(KeyConstants._required,fa.isRequired()?Boolean.TRUE:Boolean.FALSE); 167 _arg.set(KeyConstants._type,StringUtil.emptyIfNull(fa.getTypeAsString())); 168 _arg.set(KeyConstants._name,StringUtil.emptyIfNull(fa.getName())); 169 _arg.set(KeyConstants._description,StringUtil.emptyIfNull(fa.getHint())); 170 171 String status; 172 if(meta==null)status="implemeted"; 173 else status=TagLibFactory.toStatus(TagLibFactory.toStatus(Caster.toString(meta.get(KeyConstants._status,"implemeted")))); 174 175 _arg.set(KeyConstants._status,status); 176 177 _args.append(_arg); 178 } 179 sct.set(ARG_MIN,Caster.toDouble(min)); 180 sct.set(ARG_MAX,Caster.toDouble(max)); 181 182 183 return sct; 184 } 185}