001 package railo.runtime.net.amf; 002 003 import java.util.ArrayList; 004 import java.util.List; 005 import java.util.ListIterator; 006 import java.util.Map; 007 008 import org.openamf.AMFBody; 009 import org.openamf.config.OpenAMFConfig; 010 import org.openamf.config.PageableRecordsetConfig; 011 import org.openamf.recordset.ASRecordSet; 012 013 import railo.runtime.Component; 014 import railo.runtime.component.Property; 015 import railo.runtime.exp.ApplicationException; 016 import railo.runtime.exp.PageException; 017 import railo.runtime.op.Caster; 018 import railo.runtime.op.Decision; 019 import railo.runtime.type.Query; 020 import railo.runtime.type.QueryColumn; 021 import railo.runtime.type.QueryImpl; 022 import railo.runtime.type.UDF; 023 import railo.runtime.type.cfc.ComponentAccess; 024 import railo.runtime.type.util.ComponentUtil; 025 import flashgateway.io.ASObject; 026 027 /** 028 * Cast a CFML object to AMF Objects and the other way 029 */ 030 public final class OpenAMFCaster implements AMFCaster { 031 032 033 private static OpenAMFCaster singelton; 034 035 036 private OpenAMFCaster(){} 037 038 public static AMFCaster getInstance(){ 039 if(singelton==null){ 040 singelton= new OpenAMFCaster(); 041 } 042 return singelton; 043 } 044 045 /** 046 * cast cfml Object to AMF Object 047 * @param o 048 * @return 049 * @throws PageException 050 */ 051 public Object toAMFObject(Object o) throws PageException { 052 if(o instanceof ASObject) return o; 053 if(Decision.isBinary(o)) return o; 054 if(Decision.isArray(o)) return toAMFObject(Caster.toList(o,true)); 055 if(Decision.isBoolean(o)) return Caster.toBoolean(o); 056 if(Decision.isComponent(o)) return toAMFObject((Component)o); 057 if(Decision.isDateSimple(o,false))return Caster.toDate(o,null); 058 if(Decision.isNumeric(o)) return Caster.toDouble(o); 059 if(Decision.isQuery(o)) return toAMFObject(Caster.toQuery(o)); 060 if(Decision.isStruct(o)) return toAMFObject(Caster.toMap(o,true)); 061 if(Decision.isUserDefinedFunction(o)) 062 return toAMFObject((UDF)o); 063 064 065 066 return o; 067 } 068 069 070 private List toAMFObject(List list) throws PageException { 071 ListIterator it = list.listIterator(); 072 while(it.hasNext()) { 073 list.set(it.nextIndex(),toAMFObject(it.next())); 074 } 075 return list; 076 } 077 private Map toAMFObject(Map map) throws PageException { 078 Object[] keys = map.keySet().toArray(); 079 for(int i=0;i<keys.length;i++) { 080 Object key=keys[i]; 081 Object value=map.get(key); 082 if(key instanceof String) { 083 map.remove(key); 084 key=((String)key).toUpperCase(); 085 } 086 map.put(key,toAMFObject(value)); 087 } 088 return map; 089 } 090 private Object toAMFObject(Component c) throws PageException { 091 ASObject aso = new ASObject(); 092 if(c instanceof ComponentAccess) { 093 Property[] prop = ComponentUtil.getProperties(c,false); 094 if(prop!=null)for(int i=0;i<prop.length;i++) { 095 aso.put(prop[i].getName().toUpperCase(), toAMFObject(c.get(prop[i].getName(),null))); 096 } 097 } 098 return aso; 099 } 100 private ASRecordSet toAMFObject(Query qry) throws PageException { 101 PageableRecordsetConfig prsc = new PageableRecordsetConfig(); 102 prsc.setInitialDataRowCount(qry.getRowCount()); 103 OpenAMFConfig.getInstance().setPageableRecordsetConfig(prsc); 104 105 106 ASRecordSet rs=new ASRecordSet(); 107 108 String[] keys=qry.getColumns(); 109 QueryColumn[] columns=new QueryColumn[keys.length]; 110 for(int i=0;i<columns.length;i++) { 111 columns[i]=qry.getColumn(keys[i]); 112 //rows.add(i,new ArrayList()); 113 } 114 115 116 int iCol; 117 ArrayList rows = new ArrayList(); 118 ArrayList row; 119 int rowCount=qry.getRecordcount(); 120 for(int iRow=1;iRow<=rowCount;iRow++) { 121 rows.add(row=new ArrayList()); 122 for(iCol=0;iCol<columns.length;iCol++) { 123 row.add(toAMFObject(columns[iCol].get(iRow))); 124 } 125 } 126 127 128 rs.populate(qry.getColumns(),rows); 129 130 return rs; 131 } 132 private static Object toAMFObject(UDF udf) throws PageException { 133 throw new ApplicationException("can't send a User Defined Function ("+udf.getFunctionName()+") via flash remoting"); 134 } 135 136 public Object toCFMLObject(Object amf) throws PageException { 137 if(amf instanceof List) return toCFMLObject((List)amf); 138 if(amf instanceof Map) return toCFMLObject((Map)amf); 139 if(amf instanceof ASRecordSet) return toCFMLObject((ASRecordSet)amf); 140 141 return amf; 142 } 143 private List toCFMLObject(List list) throws PageException { 144 ListIterator it = list.listIterator(); 145 while(it.hasNext()) { 146 list.set(it.nextIndex(),toCFMLObject(it.next())); 147 } 148 return list; 149 } 150 151 private Map toCFMLObject(Map map) throws PageException { 152 Object[] keys = map.keySet().toArray(); 153 for(int i=0;i<keys.length;i++) { 154 Object key=keys[i]; 155 map.put(key,toCFMLObject(map.get(key))); 156 } 157 return map; 158 } 159 160 private Query toCFMLObject(ASRecordSet rs) throws PageException { 161 String[] columns = rs.getColumnNames(); 162 List rows = rs.rows(); 163 int len=0; 164 if(rows.size()>0) len=((List)rows.get(0)).size(); 165 Query qry=new QueryImpl(columns,len,"query"); 166 167 List row; 168 for(int iCol=0;iCol<columns.length;iCol++) { 169 row=(List) rows.get(iCol); 170 QueryColumn column = qry.getColumn(columns[iCol]); 171 172 for(int iRow=0;iRow<row.size();iRow++) { 173 column.set(iRow+1,toCFMLObject(row.get(iRow))); 174 } 175 } 176 return qry; 177 } 178 179 180 /** 181 * translate a AMFBody type to a String type 182 * @param type 183 * @return string type 184 */ 185 public static String toStringType(byte type) { 186 switch(type) { 187 case AMFBody.DATA_TYPE_ARRAY: return "array"; 188 case AMFBody.DATA_TYPE_AS_OBJECT: return "as object"; 189 case AMFBody.DATA_TYPE_BOOLEAN: return "boolean"; 190 case AMFBody.DATA_TYPE_CUSTOM_CLASS: return "custom"; 191 case AMFBody.DATA_TYPE_DATE: return "date"; 192 case AMFBody.DATA_TYPE_LONG_STRING: return "long string"; 193 case AMFBody.DATA_TYPE_MIXED_ARRAY: return "mixed array"; 194 case AMFBody.DATA_TYPE_MOVIE_CLIP: return "movie"; 195 case AMFBody.DATA_TYPE_NULL: return "null"; 196 case AMFBody.DATA_TYPE_NUMBER: return "number"; 197 case AMFBody.DATA_TYPE_OBJECT: return "object"; 198 case AMFBody.DATA_TYPE_OBJECT_END: return "object end"; 199 case AMFBody.DATA_TYPE_RECORDSET: return "recordset"; 200 case AMFBody.DATA_TYPE_REFERENCE_OBJECT: return "ref object"; 201 case AMFBody.DATA_TYPE_STRING: return "string"; 202 case AMFBody.DATA_TYPE_UNDEFINED: return "undefined"; 203 case AMFBody.DATA_TYPE_UNKNOWN: return "unknow"; 204 case AMFBody.DATA_TYPE_XML: return "xml"; 205 } 206 207 return ""; 208 } 209 210 public void init(Map arguments) { 211 // TODO Auto-generated method stub 212 213 } 214 }