001 package railo.runtime.type.util; 002 003 import java.util.ArrayList; 004 import java.util.HashMap; 005 import java.util.Iterator; 006 import java.util.List; 007 import java.util.Map; 008 009 import railo.commons.lang.StringUtil; 010 import railo.runtime.PageContext; 011 import railo.runtime.config.ConfigWebImpl; 012 import railo.runtime.exp.ExpressionException; 013 import railo.runtime.exp.PageException; 014 import railo.runtime.interpreter.ref.Ref; 015 import railo.runtime.interpreter.ref.cast.Casting; 016 import railo.runtime.interpreter.ref.func.BIFCall; 017 import railo.runtime.interpreter.ref.literal.LFunctionValue; 018 import railo.runtime.interpreter.ref.literal.LString; 019 import railo.runtime.reflection.Reflector; 020 import railo.runtime.type.Collection; 021 import railo.runtime.type.Collection.Key; 022 import railo.runtime.type.KeyImpl; 023 import railo.runtime.type.Struct; 024 import railo.transformer.library.function.FunctionLib; 025 import railo.transformer.library.function.FunctionLibFunction; 026 import railo.transformer.library.function.FunctionLibFunctionArg; 027 028 public class MemberUtil { 029 030 private static final Object DEFAULT_VALUE = new Object(); 031 private static Map<Short,Map<Collection.Key,FunctionLibFunction>> matches=new HashMap<Short, Map<Collection.Key,FunctionLibFunction>>(); 032 033 public static Map<Collection.Key,FunctionLibFunction> getMembers(PageContext pc, short type) { 034 035 Map<Key, FunctionLibFunction> match = matches.get(type); 036 if(match!=null) return match; 037 038 FunctionLib[] flds = ((ConfigWebImpl)pc.getConfig()).getFLDs(); 039 Iterator<FunctionLibFunction> it; 040 FunctionLibFunction f; 041 match=new HashMap<Collection.Key,FunctionLibFunction>(); 042 for(int i=0;i<flds.length;i++){ 043 it = flds[i].getFunctions().values().iterator(); 044 while(it.hasNext()){ 045 f = it.next(); 046 if(f.getMemberName()!=null && f.getMemberType()==type && f.getArgType()==FunctionLibFunction.ARG_FIX) { 047 match.put(KeyImpl.getInstance(f.getMemberName()),f); 048 } 049 } 050 } 051 matches.put(type, match); 052 return match; 053 } 054 055 public static Object call(PageContext pc, Object coll,Collection.Key methodName, Object[] args, short type, String strType) throws PageException { 056 Map<Key, FunctionLibFunction> members = getMembers(pc, type); 057 FunctionLibFunction member=members.get(methodName); 058 059 if(member!=null){ 060 List<FunctionLibFunctionArg> _args = member.getArg(); 061 FunctionLibFunctionArg arg; 062 if(args.length<_args.size()){ 063 ArrayList<Ref> refs=new ArrayList<Ref>(); 064 refs.add(new Casting(strType,type,coll)); 065 for(int y=0;y<args.length;y++){ 066 arg = _args.get(y+1); 067 refs.add(new Casting(arg.getTypeAsString(),arg.getType(),args[y])); 068 } 069 return new BIFCall(coll, member, refs.toArray(new Ref[refs.size()])).getValue(pc); 070 } 071 072 } 073 if(pc.getConfig().getSecurityManager().getAccess(railo.runtime.security.SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==railo.runtime.security.SecurityManager.VALUE_YES) { 074 return Reflector.callMethod(coll,methodName,args); 075 //Object res = Reflector.callMethod(coll,methodName,args,DEFAULT_VALUE); 076 //if(res!=DEFAULT_VALUE) return res; 077 } 078 throw new ExpressionException("No matching function member ["+methodName+"] found, available function members are ["+railo.runtime.type.util.ListUtil.sort(CollectionUtil.getKeyList(members.keySet().iterator(), ","),"textnocase","asc",",")+"]"); 079 } 080 081 public static Object callWithNamedValues(PageContext pc,Object coll, Collection.Key methodName, Struct args,short type, String strType) throws PageException { 082 Map<Key, FunctionLibFunction> members = getMembers(pc, type); 083 FunctionLibFunction member=members.get(methodName); 084 085 if(member!=null){ 086 List<FunctionLibFunctionArg> _args = member.getArg(); 087 FunctionLibFunctionArg arg; 088 if(args.size()<_args.size()){ 089 Object val; 090 ArrayList<Ref> refs=new ArrayList<Ref>(); 091 arg=_args.get(0); 092 refs.add(new Casting(arg.getTypeAsString(),arg.getType(),new LFunctionValue(new LString(arg.getName()),coll))); 093 for(int y=1;y<_args.size();y++){ 094 arg = _args.get(y); 095 096 // match by name 097 val = args.get(arg.getName(),null); 098 099 //match by alias 100 if(val==null) { 101 String alias=arg.getAlias(); 102 if(!StringUtil.isEmpty(alias,true)) { 103 String[] aliases = railo.runtime.type.util.ListUtil.trimItems(railo.runtime.type.util.ListUtil.listToStringArray(alias,',')); 104 for(int x=0;x<aliases.length;x++){ 105 val = args.get(aliases[x],null); 106 if(val!=null) break; 107 } 108 } 109 } 110 111 if(val==null) { 112 if(arg.getRequired()) { 113 throw new ExpressionException("missing required argument ["+arg.getName()+"] for member function call ["+member.getMemberName()+"]"); 114 } 115 } 116 else{ 117 refs.add(new Casting(arg.getTypeAsString(),arg.getType(),new LFunctionValue(new LString(arg.getName()),val))); 118 //refs.add(new LFunctionValue(new LString(arg.getName()),new Casting(pc,arg.getTypeAsString(),arg.getType(),val))); 119 } 120 121 } 122 return new BIFCall(coll,member, refs.toArray(new Ref[refs.size()])).getValue(pc); 123 } 124 125 } 126 throw new ExpressionException("No matching function member ["+methodName+"] for call with named arguments found, available function members are ["+railo.runtime.type.util.ListUtil.sort(CollectionUtil.getKeyList(members.keySet().iterator(), ","),"textnocase","asc",",")+"]"); 127 } 128 129 }