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