001 package railo.runtime.net.amf; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 import java.util.List; 006 import java.util.ListIterator; 007 import java.util.Map; 008 import java.util.Map.Entry; 009 010 import railo.commons.lang.CFTypes; 011 import railo.commons.lang.StringUtil; 012 import railo.runtime.Component; 013 import railo.runtime.ComponentWrap; 014 import railo.runtime.engine.ThreadLocalPageContext; 015 import railo.runtime.exp.PageException; 016 import railo.runtime.op.Caster; 017 import railo.runtime.op.Duplicator; 018 import railo.runtime.type.Array; 019 import railo.runtime.type.Collection; 020 import railo.runtime.type.KeyImpl; 021 import railo.runtime.type.Query; 022 import railo.runtime.type.UDF; 023 import railo.runtime.type.cfc.ComponentAccess; 024 import railo.runtime.type.util.ArrayUtil; 025 import railo.runtime.type.wrap.ArrayAsList; 026 import flex.messaging.io.amf.ASObject; 027 028 029 /** 030 * Cast a CFML object to AMF Objects and the other way 031 */ 032 public final class ModernAMFCaster extends ClassicAMFCaster { 033 034 private boolean doProperties=true; 035 private boolean doGetters=true; 036 private boolean doRemoteValues=true; 037 038 @Override 039 public void init(Map arguments){ 040 super.init(arguments); 041 042 String strValues = Caster.toString(arguments.get("component-values"),null); 043 if(!StringUtil.isEmpty(strValues)){ 044 doProperties = railo.runtime.type.util.ListUtil.listFindNoCase(strValues, "properties")!=-1; 045 doGetters=railo.runtime.type.util.ListUtil.listFindNoCase(strValues, "getters")!=-1; 046 doRemoteValues=railo.runtime.type.util.ListUtil.listFindNoCase(strValues, "remote-values")!=-1; 047 } 048 } 049 050 public Object toAMFObject(Object cf) throws PageException { 051 if(cf instanceof List) return toAMFObject((List)cf); 052 if(cf instanceof Array) return toAMFObject(ArrayAsList.toList((Array)cf)); 053 if(cf instanceof Component) return toAMFObject((Component)cf); 054 if(cf instanceof Query) return super.toAMFObject((Query)cf); 055 if(cf instanceof Map) return super.toAMFObject((Map)cf); 056 if(cf instanceof Object[]) return toAMFObject((Object[])cf); 057 058 return cf; 059 } 060 061 062 protected ASObject toAMFObject(Component cfc) throws PageException { 063 // add properties 064 ASObject aso = doProperties?super.toAMFObject(cfc):new ASObject(); 065 ComponentWrap cw=null; 066 if(cfc instanceof ComponentAccess)cw=ComponentWrap.toComponentWrap(Component.ACCESS_REMOTE,cfc); 067 068 Iterator it = cfc.entrySet().iterator(); 069 Map.Entry entry; 070 Object v; 071 Collection.Key k; 072 UDF udf; 073 String name; 074 while(it.hasNext()) { 075 entry=(Entry) it.next(); 076 k=KeyImpl.toKey(entry.getKey()); 077 v=entry.getValue(); 078 079 // add getters 080 if(v instanceof UDF){ 081 if(!doGetters) continue; 082 udf=(UDF) v; 083 name=udf.getFunctionName(); 084 if(!StringUtil.startsWithIgnoreCase(name, "get"))continue; 085 if(udf.getReturnType()==CFTypes.TYPE_VOID) continue; 086 if(udf.getFunctionArguments().length>0) continue; 087 088 try { 089 v=cfc.call(ThreadLocalPageContext.get(), name, ArrayUtil.OBJECT_EMPTY); 090 } catch (PageException e) { 091 continue; 092 } 093 name=name.substring(3); 094 095 aso.put(toString(name,forceCFCLower), toAMFObject(v)); 096 } 097 098 // add remote data members 099 if(cw!=null && doRemoteValues){ 100 v=cw.get(k,null); 101 if(v!=null)aso.put(toString(k,forceCFCLower), toAMFObject(v)); 102 } 103 } 104 return aso; 105 } 106 107 protected Object toAMFObject(List list) throws PageException { 108 list = Duplicator.duplicateList(list, false); 109 ListIterator it = list.listIterator(); 110 while(it.hasNext()) { 111 list.set(it.nextIndex(),toAMFObject(it.next())); 112 } 113 return list; 114 } 115 116 protected Object toAMFObject(Object[] src) throws PageException { 117 ArrayList list=new ArrayList(); 118 for(int i=0;i<src.length;i++){ 119 list.add(toAMFObject(src[i])); 120 } 121 return list; 122 } 123 }