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 /** 039 * @see railo.runtime.net.amf.ClassicAMFCaster#init(java.util.Map) 040 */ 041 public void init(Map arguments){ 042 super.init(arguments); 043 044 String strValues = Caster.toString(arguments.get("component-values"),null); 045 if(!StringUtil.isEmpty(strValues)){ 046 doProperties = railo.runtime.type.List.listFindNoCase(strValues, "properties")!=-1; 047 doGetters=railo.runtime.type.List.listFindNoCase(strValues, "getters")!=-1; 048 doRemoteValues=railo.runtime.type.List.listFindNoCase(strValues, "remote-values")!=-1; 049 } 050 } 051 052 public Object toAMFObject(Object cf) throws PageException { 053 if(cf instanceof List) return toAMFObject((List)cf); 054 if(cf instanceof Array) return toAMFObject(ArrayAsList.toList((Array)cf)); 055 if(cf instanceof Component) return toAMFObject((Component)cf); 056 if(cf instanceof Query) return super.toAMFObject((Query)cf); 057 if(cf instanceof Map) return super.toAMFObject((Map)cf); 058 if(cf instanceof Object[]) return toAMFObject((Object[])cf); 059 060 return cf; 061 } 062 063 064 protected ASObject toAMFObject(Component cfc) throws PageException { 065 // add properties 066 ASObject aso = doProperties?super.toAMFObject(cfc):new ASObject(); 067 ComponentWrap cw=null; 068 if(cfc instanceof ComponentAccess)cw=ComponentWrap.toComponentWrap(Component.ACCESS_REMOTE,cfc); 069 070 Iterator it = cfc.entrySet().iterator(); 071 Map.Entry entry; 072 Object v; 073 Collection.Key k; 074 UDF udf; 075 String name; 076 while(it.hasNext()) { 077 entry=(Entry) it.next(); 078 k=KeyImpl.toKey(entry.getKey()); 079 v=entry.getValue(); 080 081 // add getters 082 if(v instanceof UDF){ 083 if(!doGetters) continue; 084 udf=(UDF) v; 085 name=udf.getFunctionName(); 086 if(!StringUtil.startsWithIgnoreCase(name, "get"))continue; 087 if(udf.getReturnType()==CFTypes.TYPE_VOID) continue; 088 if(udf.getFunctionArguments().length>0) continue; 089 090 try { 091 v=cfc.call(ThreadLocalPageContext.get(), name, ArrayUtil.OBJECT_EMPTY); 092 } catch (PageException e) { 093 continue; 094 } 095 name=name.substring(3); 096 097 aso.put(toString(name,forceCFCLower), toAMFObject(v)); 098 } 099 100 // add remote data members 101 if(cw!=null && doRemoteValues){ 102 v=cw.get(k,null); 103 if(v!=null)aso.put(toString(k,forceCFCLower), toAMFObject(v)); 104 } 105 } 106 return aso; 107 } 108 109 protected Object toAMFObject(List list) throws PageException { 110 list = Duplicator.duplicateList(list, false); 111 ListIterator it = list.listIterator(); 112 while(it.hasNext()) { 113 list.set(it.nextIndex(),toAMFObject(it.next())); 114 } 115 return list; 116 } 117 118 protected Object toAMFObject(Object[] src) throws PageException { 119 ArrayList list=new ArrayList(); 120 for(int i=0;i<src.length;i++){ 121 list.add(toAMFObject(src[i])); 122 } 123 return list; 124 } 125 }