package railo.runtime.type.util; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import railo.commons.lang.StringUtil; import railo.runtime.PageContext; import railo.runtime.config.ConfigWebImpl; import railo.runtime.exp.ExpressionException; import railo.runtime.exp.PageException; import railo.runtime.interpreter.ref.Ref; import railo.runtime.interpreter.ref.cast.Casting; import railo.runtime.interpreter.ref.func.BIFCall; import railo.runtime.interpreter.ref.literal.LFunctionValue; import railo.runtime.interpreter.ref.literal.LString; import railo.runtime.reflection.Reflector; import railo.runtime.type.Collection; import railo.runtime.type.Collection.Key; import railo.runtime.type.KeyImpl; import railo.runtime.type.Struct; import railo.transformer.library.function.FunctionLib; import railo.transformer.library.function.FunctionLibFunction; import railo.transformer.library.function.FunctionLibFunctionArg; public class MemberUtil { private static final Object DEFAULT_VALUE = new Object(); private static Map<Short,Map<Collection.Key,FunctionLibFunction>> matches=new HashMap<Short, Map<Collection.Key,FunctionLibFunction>>(); public static Map<Collection.Key,FunctionLibFunction> getMembers(PageContext pc, short type) { Map<Key, FunctionLibFunction> match = matches.get(type); if(match!=null) return match; FunctionLib[] flds = ((ConfigWebImpl)pc.getConfig()).getFLDs(); Iterator<FunctionLibFunction> it; FunctionLibFunction f; match=new HashMap<Collection.Key,FunctionLibFunction>(); for(int i=0;i<flds.length;i++){ it = flds[i].getFunctions().values().iterator(); while(it.hasNext()){ f = it.next(); if(f.getMemberName()!=null && f.getMemberType()==type && f.getArgType()==FunctionLibFunction.ARG_FIX) { match.put(KeyImpl.getInstance(f.getMemberName()),f); } } } matches.put(type, match); return match; } public static Object call(PageContext pc, Object coll,Collection.Key methodName, Object[] args, short type, String strType) throws PageException { Map<Key, FunctionLibFunction> members = getMembers(pc, type); FunctionLibFunction member=members.get(methodName); if(member!=null){ List<FunctionLibFunctionArg> _args = member.getArg(); FunctionLibFunctionArg arg; if(args.length<_args.size()){ ArrayList<Ref> refs=new ArrayList<Ref>(); refs.add(new Casting(strType,type,coll)); for(int y=0;y<args.length;y++){ arg = _args.get(y+1); refs.add(new Casting(arg.getTypeAsString(),arg.getType(),args[y])); } return new BIFCall(coll, member, refs.toArray(new Ref[refs.size()])).getValue(pc); } } if(pc.getConfig().getSecurityManager().getAccess(railo.runtime.security.SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==railo.runtime.security.SecurityManager.VALUE_YES) { return Reflector.callMethod(coll,methodName,args); //Object res = Reflector.callMethod(coll,methodName,args,DEFAULT_VALUE); //if(res!=DEFAULT_VALUE) return res; } 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",",")+"]"); } public static Object callWithNamedValues(PageContext pc,Object coll, Collection.Key methodName, Struct args,short type, String strType) throws PageException { Map<Key, FunctionLibFunction> members = getMembers(pc, type); FunctionLibFunction member=members.get(methodName); if(member!=null){ List<FunctionLibFunctionArg> _args = member.getArg(); FunctionLibFunctionArg arg; if(args.size()<_args.size()){ Object val; ArrayList<Ref> refs=new ArrayList<Ref>(); arg=_args.get(0); refs.add(new Casting(arg.getTypeAsString(),arg.getType(),new LFunctionValue(new LString(arg.getName()),coll))); for(int y=1;y<_args.size();y++){ arg = _args.get(y); // match by name val = args.get(arg.getName(),null); //match by alias if(val==null) { String alias=arg.getAlias(); if(!StringUtil.isEmpty(alias,true)) { String[] aliases = railo.runtime.type.util.ListUtil.trimItems(railo.runtime.type.util.ListUtil.listToStringArray(alias,',')); for(int x=0;x<aliases.length;x++){ val = args.get(aliases[x],null); if(val!=null) break; } } } if(val==null) { if(arg.getRequired()) { throw new ExpressionException("missing required argument ["+arg.getName()+"] for member function call ["+member.getMemberName()+"]"); } } else{ refs.add(new Casting(arg.getTypeAsString(),arg.getType(),new LFunctionValue(new LString(arg.getName()),val))); //refs.add(new LFunctionValue(new LString(arg.getName()),new Casting(pc,arg.getTypeAsString(),arg.getType(),val))); } } return new BIFCall(coll,member, refs.toArray(new Ref[refs.size()])).getValue(pc); } } 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",",")+"]"); } }