001    package railo.runtime.util;
002    
003    import java.util.Iterator;
004    import java.util.List;
005    import java.util.Map;
006    
007    import org.w3c.dom.Node;
008    
009    import railo.runtime.PageContext;
010    import railo.runtime.exp.ExpressionException;
011    import railo.runtime.exp.PageException;
012    import railo.runtime.op.Caster;
013    import railo.runtime.op.Decision;
014    import railo.runtime.reflection.Reflector;
015    import railo.runtime.security.SecurityManager;
016    import railo.runtime.text.xml.XMLUtil;
017    import railo.runtime.text.xml.struct.XMLStructFactory;
018    import railo.runtime.type.Collection;
019    import railo.runtime.type.FunctionValue;
020    import railo.runtime.type.KeyImpl;
021    import railo.runtime.type.Objects;
022    import railo.runtime.type.Query;
023    import railo.runtime.type.QueryImpl;
024    import railo.runtime.type.Struct;
025    import railo.runtime.type.UDF;
026    import railo.runtime.type.scope.Undefined;
027    import railo.runtime.type.util.ArrayUtil;
028    import railo.runtime.type.util.Type;
029    import railo.runtime.type.wrap.MapAsStruct;
030    
031    /**
032     * Class to handle CF Variables (set,get,call)
033     */
034    public final class VariableUtilImpl implements VariableUtil {
035    
036        
037            /**
038         * @see railo.runtime.util.VariableUtil#getCollectionEL(railo.runtime.PageContext, java.lang.Object, java.lang.String)
039         */
040        public Object getCollection(PageContext pc, Object coll, String key, Object defaultValue) {
041            if(coll instanceof Query) {
042                    // TODO sollte nicht null sein
043                return ((Query)coll).getColumn(key,null);
044            }
045            return get(pc,coll,key,defaultValue);
046        }
047        
048        public Object getCollection(PageContext pc, Object coll, Collection.Key key, Object defaultValue) {
049            if(coll instanceof Query) {
050                    // TODO sollte nicht null sein
051                return ((Query)coll).getColumn(key,null);
052            }
053            return get(pc,coll,key,defaultValue);
054        }
055    
056            /**
057             *
058             * @see railo.runtime.util.VariableUtil#get(railo.runtime.PageContext, java.lang.Object, java.lang.String, java.lang.Object)
059             */
060            public Object get(PageContext pc, Object coll, String key, Object defaultValue) {
061            // Objects
062            if(coll instanceof Objects) {
063                return ((Objects)coll).get(pc,key,defaultValue);
064            }
065                    // Collection
066            else if(coll instanceof Collection) {
067                return ((Collection)coll).get(key,defaultValue);
068            } 
069                    // Map
070                    else if(coll instanceof Map) {
071                            Object rtn=((Map)coll).get(key);
072                            //if(rtn==null)rtn=((Map)coll).get(MapAsStruct.getCaseSensitiveKey((Map)coll, key));
073                            if(rtn!=null) return rtn;
074                            return defaultValue;
075                    } 
076                    // List
077                    else if(coll instanceof List) {
078                            int index=Caster.toIntValue(key,Integer.MIN_VALUE);
079                        if(index==Integer.MIN_VALUE) return defaultValue;
080                        try {
081                            return ((List)coll).get(index-1);
082                        }
083                        catch(IndexOutOfBoundsException e) {
084                            return defaultValue;
085                        }
086                    }
087                    // Native Array
088                    else if(Decision.isNativeArray(coll)) {
089                            return ArrayUtil.get(coll,Caster.toIntValue(key,Integer.MIN_VALUE)-1,defaultValue);
090                    }
091                    // Node
092                    else if(coll instanceof Node) {
093                        return XMLStructFactory.newInstance((Node)coll,false).get(key,defaultValue);
094                    }
095            // Direct Object Access
096            if(pc.getConfig().getSecurityManager().getAccess(SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==SecurityManager.VALUE_YES) {
097                            return Reflector.getProperty(coll,key,defaultValue);
098                    }
099                    return null;
100                    
101            }
102            // FUTURE add all Key functions like this to interface
103            public Object get(PageContext pc, Object coll, Collection.Key key, Object defaultValue) {
104            // Objects
105                    //print.out("key:"+key.getString());
106                    if(coll instanceof Objects) {
107                return ((Objects)coll).get(pc,key,defaultValue);
108            }
109                    // Collection
110            else if(coll instanceof Collection) {
111                return ((Collection)coll).get(key,defaultValue);
112            } 
113                    // Map
114                    else if(coll instanceof Map) {
115                            
116                            Object rtn=((Map)coll).get(key.getString());
117                            //if(rtn==null)rtn=((Map)coll).get(MapAsStruct.getCaseSensitiveKey((Map)coll, key.getString()));
118                            if(rtn!=null) return rtn;
119                            return defaultValue;
120                            
121                    } 
122                    // List
123                    else if(coll instanceof List) {
124                            int index=Caster.toIntValue(key,Integer.MIN_VALUE);
125                        if(index==Integer.MIN_VALUE) return defaultValue;
126                        try {
127                            return ((List)coll).get(index-1);
128                        }
129                        catch(IndexOutOfBoundsException e) {
130                            return defaultValue;
131                        }
132                    }
133                    // Native Array
134                    else if(Decision.isNativeArray(coll)) {
135                            return ArrayUtil.get(coll,Caster.toIntValue(key,Integer.MIN_VALUE)-1,defaultValue);
136                    }
137                    // Node
138                    else if(coll instanceof Node) {
139                        return XMLStructFactory.newInstance((Node)coll,false).get(key,defaultValue);
140                    }
141            // Direct Object Access
142            if(pc.getConfig().getSecurityManager().getAccess(SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==SecurityManager.VALUE_YES) {
143                            return Reflector.getProperty(coll,key.getString(),defaultValue);
144                    }
145                    return null;
146                    
147            }
148            
149            public Object getLight(PageContext pc, Object coll, Collection.Key key, Object defaultValue) {
150            // Objects
151            if(coll instanceof Objects) {
152                return ((Objects)coll).get(pc,key,defaultValue);
153            }
154                    // Collection
155            else if(coll instanceof Collection) {
156                            return ((Collection)coll).get(key,defaultValue);
157                    } 
158                    // Map
159                    else if(coll instanceof Map) {
160                            //Object rtn=null;
161                            try {
162                                    Object rtn=((Map)coll).get(key.getString());
163                                    //if(rtn==null)rtn=((Map)coll).get(MapAsStruct.getCaseSensitiveKey((Map)coll, key.getString()));
164                                    if(rtn!=null) return rtn;
165                            }
166                            catch(Throwable t) {}
167                            return Reflector.getField(coll,key.getString(),defaultValue);
168                            //return rtn;
169                    } 
170                    // List
171                    else if(coll instanceof List) {
172                            int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE);
173                        if(index==Integer.MIN_VALUE) return null;
174                        try {
175                            return ((List)coll).get(index-1);
176                        }
177                        catch(IndexOutOfBoundsException e) {
178                            return defaultValue;
179                        }
180                    }
181                    return defaultValue;
182            }
183            
184            /**
185         * @see railo.runtime.util.VariableUtil#getLightEL(railo.runtime.PageContext, java.lang.Object, java.lang.String)
186         */
187            public Object getLight(PageContext pc, Object coll, String key, Object defaultValue) {
188            // Objects
189            if(coll instanceof Objects) {
190                return ((Objects)coll).get(pc,key,defaultValue);
191            }
192                    // Collection
193            else if(coll instanceof Collection) {
194                            return ((Collection)coll).get(key,defaultValue);
195                    } 
196                    // Map
197                    else if(coll instanceof Map) {
198                            try {
199                                    Object rtn=((Map)coll).get(key);
200                                    //if(rtn==null)rtn=((Map)coll).get(MapAsStruct.getCaseSensitiveKey((Map)coll, key));
201                                    if(rtn!=null) return rtn;
202                            }
203                            catch(Throwable t) {}
204                            return Reflector.getProperty(coll,key,defaultValue);
205                            //return rtn;
206                    } 
207                    // List
208                    else if(coll instanceof List) {
209                            int index=Caster.toIntValue(key,Integer.MIN_VALUE);
210                        if(index==Integer.MIN_VALUE) return null;
211                        try {
212                            return ((List)coll).get(index-1);
213                        }
214                        catch(IndexOutOfBoundsException e) {
215                            return defaultValue;
216                        }
217                    }
218                    return defaultValue;
219            }
220            
221        /**
222         * @see railo.runtime.util.VariableUtil#getCollection(railo.runtime.PageContext, java.lang.Object, java.lang.String)
223         */
224        public Object getCollection(PageContext pc, Object coll, String key) throws PageException {
225            if(coll instanceof Query) {
226                return ((Query)coll).getColumn(key);
227            }
228            return get(pc,coll,key);
229        }
230        public Object getCollection(PageContext pc, Object coll, Collection.Key key) throws PageException {
231            if(coll instanceof Query) {
232                return ((Query)coll).getColumn(key);
233            }
234            return get(pc,coll,key);
235        }
236        
237        public Object get(PageContext pc, Object coll, Collection.Key key) throws PageException {
238            // Objects
239            if(coll instanceof Objects) {
240                return ((Objects)coll).get(pc,key);
241            }
242            // Collection
243            else if(coll instanceof Collection) {
244                return ((Collection)coll).get(key);
245                    } 
246                    // Map
247                    else if(coll instanceof Map) {
248                            Object rtn=null;
249                            try {
250                                    rtn=((Map)coll).get(key.getString());
251                                    if(rtn==null && coll.getClass().getName().startsWith("org.hibernate."))
252                                            rtn=((Map)coll).get(MapAsStruct.getCaseSensitiveKey((Map)coll, key.getString()));
253                                    if(rtn!=null) return rtn;
254                            }
255                            catch(Throwable t) {}
256                            rtn = Reflector.getProperty(coll,key.getString(),null);
257                            if(rtn!=null) return rtn;
258                            
259                            String realKey = MapAsStruct.getCaseSensitiveKey((Map)coll, key.getString());
260                            String detail=null;
261                            if(realKey!=null) {
262                                    detail="The keys for this Map are case-sensitive, use bracked notation like this \"map['"+realKey+"']\" instead of dot notation like this  \"map."+realKey+"\" to address the Map";
263                            }
264                            
265                            throw new ExpressionException("Key ["+key.getString()+"] doesn't exist in Map ("+((Map)coll).getClass().getName()+")",detail);
266                                            //,"keys are ["+railo.runtime.type.List.arrayToList(MapAsStruct.toStruct((Map)coll, true).keysAsString(),",")+"]");
267                    } 
268                    // List
269                    else if(coll instanceof List) {
270                        try {
271                            Object rtn=((List)coll).get(Caster.toIntValue(key.getString())-1);
272                            if(rtn==null) throw new ExpressionException("Key ["+key.getString()+"] doesn't exist in List");
273                                    return rtn;
274                        }
275                        catch(IndexOutOfBoundsException e) {
276                            throw new ExpressionException("Key ["+key.getString()+"] doesn't exist in List");
277                        }
278                    }
279                    // Native Array
280                    else if(Decision.isNativeArray(coll)) {
281                            Object rtn=ArrayUtil.get(coll,Caster.toIntValue(key.getString())-1,null);
282                            if(rtn==null) throw new ExpressionException("Key ["+key.getString()+"] doesn't exist in Native Array");
283                            return rtn;
284                    }
285            // Node
286                    else if(coll instanceof Node) {
287                            //print.out("get:"+key);
288                return XMLStructFactory.newInstance((Node)coll,false).get(key);
289            }
290            // HTTPSession
291                    /*else if(coll instanceof HttpSession) {
292                return ((HttpSession)coll).getAttribute(key.getString());
293            }*/
294            
295            
296            
297            // Direct Object Access
298                    if(coll!=null && pc.getConfig().getSecurityManager().getAccess(SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==SecurityManager.VALUE_YES) {
299                            return Reflector.getProperty(coll,key.getString());
300                    }
301                    throw new ExpressionException("No matching property ["+key.getString()+"] found");
302            
303        }
304        
305        /**
306         * @see railo.runtime.util.VariableUtil#get(railo.runtime.PageContext, java.lang.Object, java.lang.String)
307         */
308        public Object get(PageContext pc, Object coll, String key) throws PageException {
309            // Objects
310            if(coll instanceof Objects) {
311                return ((Objects)coll).get(pc,key);
312            }
313            // Collection
314            else if(coll instanceof Collection) {
315                
316                            return ((Collection)coll).get(key);
317                    } 
318                    // Map
319                    else if(coll instanceof Map) {
320                            Object rtn=null;
321                            try {
322                                    rtn=((Map)coll).get(key);
323                                    //if(rtn==null)rtn=((Map)coll).get(MapAsStruct.getCaseSensitiveKey((Map)coll, key));
324                                    if(rtn!=null) return rtn;
325                                    
326                            }
327                            catch(Throwable t) {}
328                            rtn = Reflector.getProperty(coll,key,null);
329                            if(rtn!=null) return rtn;
330                            throw new ExpressionException("Key ["+key+"] doesn't exist in Map ("+Caster.toClassName(coll)+")","keys are ["+keyList(((Map)coll))+"]");
331                    } 
332                    // List
333                    else if(coll instanceof List) {
334                        try {
335                            Object rtn=((List)coll).get(Caster.toIntValue(key)-1);
336                            if(rtn==null) throw new ExpressionException("Key ["+key+"] doesn't exist in List");
337                                    return rtn;
338                        }
339                        catch(IndexOutOfBoundsException e) {
340                            throw new ExpressionException("Key ["+key+"] doesn't exist in List");
341                        }
342                    }
343                    // Native Array
344                    else if(Decision.isNativeArray(coll)) {
345                            Object rtn=ArrayUtil.get(coll,Caster.toIntValue(key)-1,null);
346                            if(rtn==null) throw new ExpressionException("Key ["+key+"] doesn't exist in Native Array");
347                            return rtn;
348                    }
349            // Node
350            else if(coll instanceof Node) {
351                return XMLStructFactory.newInstance((Node)coll,false).get(key);
352            }
353            // Direct Object Access
354                    if(pc.getConfig().getSecurityManager().getAccess(SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==SecurityManager.VALUE_YES) {
355                            return Reflector.getProperty(coll,key);
356                    }
357                    throw new ExpressionException("No matching property ["+key+"] found");
358            
359        }
360    
361    
362        private String keyList(Map map) {
363            StringBuffer sb=new StringBuffer();
364                    Iterator it = map.keySet().iterator();
365                    while(it.hasNext()) {
366                            if(sb.length()>0)sb.append(',');
367                            sb.append(it.next().toString());
368                    }
369                    return sb.toString();
370            }
371    
372            public Object set(PageContext pc, Object coll, Collection.Key key,Object value) throws PageException {
373            // Objects
374            if(coll instanceof Objects) { 
375                ((Objects)coll).set(pc,key,value);
376                return value;
377            }
378            // Collection
379            else if(coll instanceof Collection) { 
380                ((Collection)coll).set(key,value);
381                return value;
382            }
383                    // Map
384                    else if(coll instanceof Map) {
385                            /* no idea why this is here
386                            try {
387                                    Reflector.setProperty(coll,key.getString(),value);
388                                    return value;
389                            }
390                            catch(Throwable t) {t.printStackTrace();}*/
391                            ((Map)coll).put(key.getString(),value);
392                            return value;
393                    } 
394                    // List
395                    else if(coll instanceof List) {
396                        List list=((List)coll);
397                        int index=Caster.toIntValue(key.getString());
398                        if(list.size()>=index)list.set(index-1,value);
399                        else {
400                            while(list.size()<index-1)list.add(null);
401                            list.add(value);
402                        }
403                            return value;
404                    }
405                    // Native Array
406                    else if(Decision.isNativeArray(coll)) {
407                            try {
408                    return ArrayUtil.set(coll,Caster.toIntValue(key.getString())-1,value);
409                } catch (Exception e) {
410                    throw new ExpressionException("invalid index ["+key.getString()+"] for Native Array, can't expand Native Arrays");
411                }
412                    }
413                    // Node
414                    else if(coll instanceof Node) {
415                            return XMLUtil.setProperty((Node)coll,key,value);
416                    }
417            // Direct Object Access
418                    if(pc.getConfig().getSecurityManager().getAccess(SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==SecurityManager.VALUE_YES) {
419                            try {
420                            Reflector.setProperty(coll,key.getString(),value);
421                            return value;
422                        }
423                        catch(PageException pe) {} 
424                    }       
425                    throw new ExpressionException("can't assign value to a Object of this type ["+Type.getName(coll)+"] with key "+key.getString());
426        }
427        
428        
429        /**
430         * @see railo.runtime.util.VariableUtil#set(railo.runtime.PageContext, java.lang.Object, java.lang.String, java.lang.Object)
431         */
432        public Object set(PageContext pc, Object coll, String key,Object value) throws PageException {
433            // Objects
434            if(coll instanceof Objects) { 
435                ((Objects)coll).set(pc,key,value);
436                return value;
437            }
438            // Collection
439            else if(coll instanceof Collection) { 
440                ((Collection)coll).set(key,value);
441                return value;
442            }
443                    // Map
444                    else if(coll instanceof Map) {
445                            /*try {
446                                    Reflector.setProperty(coll,key,value);
447                                    return value;
448                            }
449                            catch(Throwable t) {}*/
450                            ((Map)coll).put(key,value);
451                            return value;
452                    } 
453                    // List
454                    else if(coll instanceof List) {
455                        List list=((List)coll);
456                        int index=Caster.toIntValue(key);
457                        if(list.size()>=index)list.set(index-1,value);
458                        else {
459                            while(list.size()<index-1)list.add(null);
460                            list.add(value);
461                        }
462                            return value;
463                    }
464                    // Native Array
465                    else if(Decision.isNativeArray(coll)) {
466                            try {
467                    return ArrayUtil.set(coll,Caster.toIntValue(key)-1,value);
468                } catch (Exception e) {
469                    throw new ExpressionException("invalid index ["+key+"] for Native Array, can't expand Native Arrays");
470                }
471                    }
472                    // Node
473                    else if(coll instanceof Node) {
474                            return XMLUtil.setProperty((Node)coll,KeyImpl.init(key),value);
475                    }
476            // Direct Object Access
477                    if(pc.getConfig().getSecurityManager().getAccess(SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==SecurityManager.VALUE_YES) {
478                            try {
479                            Reflector.setProperty(coll,key,value);
480                            return value;
481                        }
482                        catch(PageException pe) {} 
483                    }       
484                    throw new ExpressionException("can't assign value to a Object of this type ["+Type.getName(coll)+"] with key "+key);
485        }
486        
487        /**
488         *
489         * @see railo.runtime.util.VariableUtil#setEL(railo.runtime.PageContext, java.lang.Object, java.lang.String, java.lang.Object)
490         */
491        public Object setEL(PageContext pc, Object coll, String key,Object value) {
492            // Objects
493            if(coll instanceof Objects) { 
494                ((Objects)coll).setEL(pc,key,value);
495                return value;
496            }
497            // Collection
498            else if(coll instanceof Collection) { 
499                            ((Collection)coll).setEL(key,value);
500                            return value;
501                    }
502                    // Map
503                    else if(coll instanceof Map) {
504                            try {
505                                    Reflector.setProperty(coll,key,value);
506                                    return value;
507                            }
508                            catch(Throwable t) {}
509                            ((Map)coll).put(key,value);
510                            return value;
511                    } 
512                    // List
513                    else if(coll instanceof List) {
514                        List list=((List)coll);
515                        int index=Caster.toIntValue(key,Integer.MIN_VALUE);
516                        if(index==Integer.MIN_VALUE) return null;
517                        if(list.size()>=index)list.set(index-1,value);
518                        else {
519                            while(list.size()<index-1)list.add(null);
520                            list.add(value);
521                        }
522                            return value;
523                    }
524                    // Native Array
525                    else if(Decision.isNativeArray(coll)) {
526                            return ArrayUtil.setEL(coll,Caster.toIntValue(key,Integer.MIN_VALUE)-1,value);
527                    }
528                    // Node
529                    else if(coll instanceof Node) {
530                            return XMLUtil.setPropertyEL((Node)coll,KeyImpl.init(key),value);
531                    }
532            // Direct Object Access
533                    if(pc.getConfig().getSecurityManager().getAccess(SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==SecurityManager.VALUE_YES) {
534                            Reflector.setPropertyEL(coll,key,value);
535                            return value; 
536                    }
537                    return null;
538        }
539        
540        // FUTURE add to interface
541        public Object setEL(PageContext pc, Object coll, Collection.Key key,Object value) {
542            // Objects
543            if(coll instanceof Objects) { 
544                ((Objects)coll).setEL(pc,key,value);
545                return value;
546            }
547            // Collection
548            else if(coll instanceof Collection) { 
549                            ((Collection)coll).setEL(key,value);
550                            return value;
551                    }
552                    // Map
553                    else if(coll instanceof Map) {
554                            try {
555                                    Reflector.setProperty(coll,key.getString(),value);
556                                    return value;
557                            }
558                            catch(Throwable t) {}
559                            ((Map)coll).put(key,value);
560                            return value;
561                    } 
562                    // List
563                    else if(coll instanceof List) {
564                        List list=((List)coll);
565                        int index=Caster.toIntValue(key,Integer.MIN_VALUE);
566                        if(index==Integer.MIN_VALUE) return null;
567                        if(list.size()>=index)list.set(index-1,value);
568                        else {
569                            while(list.size()<index-1)list.add(null);
570                            list.add(value);
571                        }
572                            return value;
573                    }
574                    // Native Array
575                    else if(Decision.isNativeArray(coll)) {
576                            return ArrayUtil.setEL(coll,Caster.toIntValue(key,Integer.MIN_VALUE)-1,value);
577                    }
578                    // Node
579                    else if(coll instanceof Node) {
580                            return XMLUtil.setPropertyEL((Node)coll,key,value);
581                    }
582            // Direct Object Access
583                    if(pc.getConfig().getSecurityManager().getAccess(SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==SecurityManager.VALUE_YES) {
584                            Reflector.setPropertyEL(coll,key.getString(),value);
585                            return value; 
586                    }
587                    return null;
588        }
589    
590        /**
591         *
592         * @see railo.runtime.util.VariableUtil#removeEL(java.lang.Object, java.lang.String)
593         */
594        public Object removeEL(Object coll, String key) {
595            // Collection
596            if(coll instanceof Collection) { 
597                            return ((Collection)coll).removeEL(KeyImpl.init(key));
598                    }
599                    // Map
600                    else if(coll instanceof Map) { 
601                            Object obj = ((Map)coll).remove(key);
602                            //if(obj==null)obj=((Map)coll).remove(MapAsStruct.getCaseSensitiveKey((Map)coll, key));
603                            return obj;
604                    }
605                    // List
606                    else if(coll instanceof List) {
607                        int i=Caster.toIntValue(key,Integer.MIN_VALUE);
608                        if(i==Integer.MIN_VALUE) return null;
609                        return ((List)coll).remove(i);
610                    }
611                    return null;
612        }
613        
614        public Object removeEL(Object coll, Collection.Key key) {
615            // Collection
616            if(coll instanceof Collection) { 
617                            return ((Collection)coll).removeEL(key);
618                    }
619                    // Map
620                    else if(coll instanceof Map) { 
621                            Object obj = ((Map)coll).remove(key.getString());
622                            //if(obj==null)obj=((Map)coll).remove(MapAsStruct.getCaseSensitiveKey((Map)coll, key));
623                            return obj;
624                    }
625                    // List
626                    else if(coll instanceof List) {
627                        int i=Caster.toIntValue(key,Integer.MIN_VALUE);
628                        if(i==Integer.MIN_VALUE) return null;
629                        return ((List)coll).remove(i);
630                    }
631                    return null;
632        }
633        
634    
635        /**
636         * @see railo.runtime.util.VariableUtil#remove(java.lang.Object, java.lang.String)
637         */
638        public Object remove(Object coll, String key) throws PageException {
639            // Collection
640                    if(coll instanceof Collection) { 
641                            return ((Collection)coll).remove(KeyImpl.init(key));
642                    }
643                    // Map
644                    else if(coll instanceof Map) { 
645                            Object obj=((Map)coll).remove(key);
646                            //if(obj==null)obj=((Map)coll).remove(MapAsStruct.getCaseSensitiveKey((Map)coll, key));
647                            if(obj==null) throw new ExpressionException("can't remove key ["+key+"] from map");
648                            return obj;
649                    }
650                    // List
651                    else if(coll instanceof List) {
652                        int i=Caster.toIntValue(key);
653                        Object obj=((List)coll).remove(i);
654                            if(obj==null) throw new ExpressionException("can't remove index ["+key+"] from list");
655                            return obj;
656                    }
657                    /*/ Native Array TODO this below
658                    else if(Decision.isNativeArray(o)) {
659                            try {
660                                    return ArrayUtil.set(o,Caster.toIntValue(key)-1,value);
661                            } catch (Exception e) {
662                                    return getDirectProperty(o, key, new ExpressionException("Key doesn't exist in Native Array"),false);
663                            }
664                    }*/
665                    // TODO Support for Node
666                    throw new ExpressionException("can't remove key ["+key+"] from Object of type ["+Caster.toTypeName(coll)+"]");
667        }
668        
669        public Object remove(Object coll, Collection.Key key) throws PageException {
670            // Collection
671                    if(coll instanceof Collection) { 
672                            return ((Collection)coll).remove(key);
673                    }
674                    // Map
675                    else if(coll instanceof Map) { 
676                            Object obj=((Map)coll).remove(key.getString());
677                            //if(obj==null)obj=((Map)coll).remove(MapAsStruct.getCaseSensitiveKey((Map)coll, key));
678                            if(obj==null) throw new ExpressionException("can't remove key ["+key+"] from map");
679                            return obj;
680                    }
681                    // List
682                    else if(coll instanceof List) {
683                        int i=Caster.toIntValue(key);
684                        Object obj=((List)coll).remove(i);
685                            if(obj==null) throw new ExpressionException("can't remove index ["+key+"] from list");
686                            return obj;
687                    }
688                    /*/ Native Array TODO this below
689                    else if(Decision.isNativeArray(o)) {
690                            try {
691                                    return ArrayUtil.set(o,Caster.toIntValue(key)-1,value);
692                            } catch (Exception e) {
693                                    return getDirectProperty(o, key, new ExpressionException("Key doesn't exist in Native Array"),false);
694                            }
695                    }*/
696                    // TODO Support for Node
697                    throw new ExpressionException("can't remove key ["+key+"] from Object of type ["+Caster.toTypeName(coll)+"]");
698        }
699        
700        /**
701         * @see railo.runtime.util.VariableUtil#callFunction(railo.runtime.PageContext, java.lang.Object, java.lang.String, java.lang.Object[])
702         */
703        public Object callFunction(PageContext pc, Object coll, String key, Object[] args) throws PageException {
704                    if(args.length>0 && args[0] instanceof FunctionValue)
705                            return callFunctionWithNamedValues(pc, coll, key, args);
706                    return callFunctionWithoutNamedValues(pc, coll, key, args);
707            }
708        
709        /**
710         * @see railo.runtime.util.VariableUtil#callFunctionWithoutNamedValues(railo.runtime.PageContext, java.lang.Object, java.lang.String, java.lang.Object[])
711         */
712            public Object callFunctionWithoutNamedValues(PageContext pc, Object coll, String key, Object[] args) throws PageException {
713                
714            // Objects
715            if(coll instanceof Objects) {
716                return ((Objects)coll).call(pc,key,args);
717            }
718            // call UDF
719                Object prop=getLight(pc,coll,key,null);     
720                if(prop instanceof UDF) {
721                            return ((UDF)prop).call(pc,args,false);
722                    }
723            // call Object Wrapper      
724                if(pc.getConfig().getSecurityManager().getAccess(SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==SecurityManager.VALUE_YES) {
725                    return Reflector.callMethod(coll,key,args);
726                }
727                    throw new ExpressionException("No matching Method/Function for "+key+"("+Reflector.getDspMethods(Reflector.getClasses(args))+")");
728            }
729            
730            public Object callFunctionWithoutNamedValues(PageContext pc, Object coll, Collection.Key key, Object[] args) throws PageException {
731                // Objects
732            if(coll instanceof Objects) {
733                return ((Objects)coll).call(pc,key,args);
734            }
735            // call UDF
736                Object prop=getLight(pc,coll,key,null);     
737                if(prop instanceof UDF) {
738                            return ((UDF)prop).call(pc,args,false);
739                    }
740            // call Object Wrapper      
741                if(pc.getConfig().getSecurityManager().getAccess(SecurityManager.TYPE_DIRECT_JAVA_ACCESS)==SecurityManager.VALUE_YES) {
742                    if(!(coll instanceof Undefined))return Reflector.callMethod(coll,key,args);
743                }
744                    throw new ExpressionException("No matching Method/Function for "+key+"("+Reflector.getDspMethods(Reflector.getClasses(args))+")");
745    
746        
747            }
748            
749            /**
750         * @see railo.runtime.util.VariableUtil#callFunctionWithNamedValues(railo.runtime.PageContext, java.lang.Object, java.lang.String, java.lang.Object[])
751         */
752            public Object callFunctionWithNamedValues(PageContext pc, Object coll, String key, Object[] args) throws PageException {
753                    // Objects
754            if(coll instanceof Objects) {
755                return ((Objects)coll).callWithNamedValues(pc,key, Caster.toFunctionValues(args));
756            }
757            // call UDF
758                    Object prop=getLight(pc,coll,key,null); 
759            if(prop instanceof UDF) {
760                return ((UDF)prop).callWithNamedValues(pc,Caster.toFunctionValues(args),false);
761            }
762                    throw new ExpressionException("No matching Method/Function ["+key+"] for call with named arguments found");
763                    //throw new ExpressionException("can't use named argument for this operation");
764            }
765    
766            public Object callFunctionWithNamedValues(PageContext pc, Object coll, Collection.Key key, Object[] args) throws PageException {
767                    // Objects
768            if(coll instanceof Objects) {
769                return ((Objects)coll).callWithNamedValues(pc,key, Caster.toFunctionValues(args));
770            }
771            // call UDF
772                    Object prop=getLight(pc,coll,key,null); 
773            if(prop instanceof UDF)                 {
774                return ((UDF)prop).callWithNamedValues(pc,Caster.toFunctionValues(args),false);
775            }
776            throw new ExpressionException("No matching Method/Function ["+key+"] for call with named arguments found ");
777            }
778    
779            public Object callFunctionWithNamedValues(PageContext pc, Object coll, Collection.Key key, Struct args) throws PageException {
780                    // Objects
781            if(coll instanceof Objects) {
782                return ((Objects)coll).callWithNamedValues(pc,key, args);
783            }
784            // call UDF
785                    Object prop=getLight(pc,coll,key,null); 
786            if(prop instanceof UDF)                 {
787                return ((UDF)prop).callWithNamedValues(pc,args,false);
788            }
789            throw new ExpressionException("No matching Method/Function for call with named arguments found");
790            }
791            
792            /*
793            public Object get(Scope scope,Collection.Key key1) throws PageException{
794                    return scope.get(key1);
795            }
796            public Object undefined(PageContextImpl pc,Collection.Key key1,Collection.Key key2) throws PageException{
797                    return pc.get(pc.us().getCollection(key1),key2);
798            }
799            
800            pagecontext.get(pagecontext.us().getCollection(key1), key2);
801            pagecontext.get(pagecontext.getCollection(pagecontext.us()
802                                                          .getCollection(key1),
803                                                      key2),
804                            key3);
805            pagecontext.get((pagecontext.getCollection
806                             (pagecontext.getCollection(pagecontext.us()
807                                                            .getCollection(key1),
808                                                        key2),
809                              key3)),
810                            key4);
811        }
812            */
813            
814            
815            
816            // used by generated bytecode
817            public static Object recordcount(PageContext pc,Object obj) throws PageException{
818                    if(obj instanceof Query) return Caster.toDouble(((Query)obj).getRecordcount());
819                    return pc.getCollection(obj, QueryImpl.RECORDCOUNT);
820            }
821            // used by generated bytecode
822            public static Object currentrow(PageContext pc,Object obj) throws PageException{
823                    if(obj instanceof Query) return Caster.toDouble(((Query)obj).getCurrentrow());
824                    return pc.getCollection(obj, QueryImpl.CURRENTROW);
825            }
826            // used by generated bytecode
827            public static Object columnlist(PageContext pc,Object obj) throws PageException{
828                    if(obj instanceof Query) {
829                            String[] columnNames = ((Query)obj).getColumns();
830                            
831                            StringBuffer sb=new StringBuffer();
832                            for(int i=0;i<columnNames.length;i++) {
833                                    if(i>0)sb.append(',');
834                                    sb.append(columnNames[i].toUpperCase());
835                            }
836                            return sb.toString();
837                            
838                            
839                    }
840                    return pc.getCollection(obj, QueryImpl.COLUMNLIST);
841            }
842        
843    }