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