001 /** 002 * Implements the CFML Function getfunctiondescription 003 */ 004 package railo.runtime.functions.other; 005 006 import java.util.ArrayList; 007 008 import railo.commons.lang.CFTypes; 009 import railo.commons.lang.StringUtil; 010 import railo.runtime.PageContext; 011 import railo.runtime.config.ConfigImpl; 012 import railo.runtime.exp.ExpressionException; 013 import railo.runtime.exp.PageException; 014 import railo.runtime.ext.function.Function; 015 import railo.runtime.functions.system.CFFunction; 016 import railo.runtime.op.Caster; 017 import railo.runtime.type.Array; 018 import railo.runtime.type.ArrayImpl; 019 import railo.runtime.type.Collection; 020 import railo.runtime.type.Collection.Key; 021 import railo.runtime.type.FunctionArgument; 022 import railo.runtime.type.KeyImpl; 023 import railo.runtime.type.Struct; 024 import railo.runtime.type.StructImpl; 025 import railo.runtime.type.UDFImpl; 026 import railo.runtime.type.util.KeyConstants; 027 import railo.transformer.library.function.FunctionLib; 028 import railo.transformer.library.function.FunctionLibFunction; 029 import railo.transformer.library.function.FunctionLibFunctionArg; 030 import railo.transformer.library.tag.TagLibFactory; 031 032 public final class GetFunctionData implements Function { 033 private static final Collection.Key SOURCE = KeyConstants._source; 034 private static final Collection.Key RETURN_TYPE = KeyImpl.intern("returnType"); 035 private static final Collection.Key ARGUMENT_TYPE = KeyImpl.intern("argumentType"); 036 private static final Collection.Key ARG_MIN = KeyImpl.intern("argMin"); 037 private static final Collection.Key ARG_MAX = KeyImpl.intern("argMax"); 038 039 public static Struct call(PageContext pc , String strFunctionName) throws PageException { 040 FunctionLib[] flds; 041 flds = ((ConfigImpl)pc.getConfig()).getFLDs(); 042 043 044 FunctionLibFunction function=null; 045 for(int i=0;i<flds.length;i++) { 046 function = flds[i].getFunction(strFunctionName.toLowerCase()); 047 if(function!=null)break; 048 } 049 if(function == null) throw new ExpressionException("function ["+strFunctionName+"] is not a built in function"); 050 051 //sct.set("returnTypeClass",_class(function.getCazz())); 052 //sct.set("class",__class(function.getCazz())); 053 054 055 056 // CFML Based Function 057 Class clazz=null; 058 try{ 059 clazz=function.getClazz(); 060 } 061 catch(Throwable t){} 062 if(clazz==railo.runtime.functions.system.CFFunction.class){ 063 return cfmlBasedFunction(pc,function); 064 } 065 return javaBasedFunction(function); 066 067 068 069 } 070 071 private static Struct javaBasedFunction(FunctionLibFunction function) throws PageException { 072 Struct sct=new StructImpl(); 073 sct.set(KeyConstants._name,function.getName()); 074 sct.set(KeyConstants._status,TagLibFactory.toStatus(function.getStatus())); 075 sct.set(KeyConstants._description,StringUtil.emptyIfNull(function.getDescription())); 076 sct.set(RETURN_TYPE,StringUtil.emptyIfNull(function.getReturnTypeAsString())); 077 sct.set(ARGUMENT_TYPE,StringUtil.emptyIfNull(function.getArgTypeAsString())); 078 sct.set(ARG_MIN,Caster.toDouble(function.getArgMin())); 079 sct.set(ARG_MAX,Caster.toDouble(function.getArgMax())); 080 sct.set(KeyConstants._type,"java"); 081 String mm = function.getMemberName(); 082 if(mm!=null && function.getMemberType()!=CFTypes.TYPE_UNKNOW) { 083 StructImpl mem = new StructImpl(); 084 sct.set(KeyConstants._member, mem); 085 mem.set(KeyConstants._name,mm); 086 mem.set(KeyConstants._chaining,Caster.toBoolean(function.getMemberChaining())); 087 mem.set(KeyConstants._type, function.getMemberTypeAsString()); 088 } 089 090 Array _args=new ArrayImpl(); 091 sct.set(KeyConstants._arguments,_args); 092 if(function.getArgType()!=FunctionLibFunction.ARG_DYNAMIC){ 093 ArrayList<FunctionLibFunctionArg> args = function.getArg(); 094 for(int i=0;i<args.size();i++) { 095 FunctionLibFunctionArg arg=args.get(i); 096 Struct _arg=new StructImpl(); 097 _arg.set(KeyConstants._required,arg.getRequired()?Boolean.TRUE:Boolean.FALSE); 098 _arg.set(KeyConstants._type,StringUtil.emptyIfNull(arg.getTypeAsString())); 099 _arg.set(KeyConstants._name,StringUtil.emptyIfNull(arg.getName())); 100 _arg.set(KeyConstants._status,TagLibFactory.toStatus(arg.getStatus())); 101 _arg.set(KeyConstants._description,StringUtil.toStringEmptyIfNull(arg.getDescription())); 102 103 104 _args.append(_arg); 105 } 106 } 107 return sct; 108 } 109 110 private static Struct cfmlBasedFunction(PageContext pc, FunctionLibFunction function) throws PageException { 111 Struct sct=new StructImpl(); 112 ArrayList<FunctionLibFunctionArg> args = function.getArg(); 113 114 String filename = Caster.toString(args.get(0).getDefaultValue()); 115 Key name = KeyImpl.toKey(args.get(1).getDefaultValue()); 116 boolean isWeb = Caster.toBooleanValue(args.get(2).getDefaultValue()); 117 UDFImpl udf = (UDFImpl) CFFunction.loadUDF(pc, filename, name, isWeb); 118 119 sct.set(KeyConstants._name,function.getName()); 120 sct.set(ARGUMENT_TYPE,"fixed"); 121 sct.set(KeyConstants._description,StringUtil.emptyIfNull(udf.getHint())); 122 sct.set(RETURN_TYPE,StringUtil.emptyIfNull(udf.getReturnTypeAsString())); 123 sct.set(KeyConstants._type,"cfml"); 124 sct.set(SOURCE,udf.getPageSource().getDisplayPath()); 125 sct.set(KeyConstants._status,"implemeted"); 126 127 128 FunctionArgument[] fas = udf.getFunctionArguments(); 129 Array _args=new ArrayImpl(); 130 sct.set(KeyConstants._arguments,_args); 131 int min=0,max=0; 132 for(int i=0;i<fas.length;i++) { 133 FunctionArgument fa=fas[i]; 134 Struct meta = fa.getMetaData(); 135 136 Struct _arg=new StructImpl(); 137 if(fa.isRequired()) min++; 138 max++; 139 _arg.set(KeyConstants._required,fa.isRequired()?Boolean.TRUE:Boolean.FALSE); 140 _arg.set(KeyConstants._type,StringUtil.emptyIfNull(fa.getTypeAsString())); 141 _arg.set(KeyConstants._name,StringUtil.emptyIfNull(fa.getName())); 142 _arg.set(KeyConstants._description,StringUtil.emptyIfNull(fa.getHint())); 143 144 String status; 145 if(meta==null)status="implemeted"; 146 else status=TagLibFactory.toStatus(TagLibFactory.toStatus(Caster.toString(meta.get(KeyConstants._status,"implemeted")))); 147 148 _arg.set(KeyConstants._status,status); 149 150 _args.append(_arg); 151 } 152 sct.set(ARG_MIN,Caster.toDouble(min)); 153 sct.set(ARG_MAX,Caster.toDouble(max)); 154 155 156 return sct; 157 } 158 }