package railo.runtime.net.amf; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import java.util.Map; import org.openamf.AMFBody; import org.openamf.config.OpenAMFConfig; import org.openamf.config.PageableRecordsetConfig; import org.openamf.recordset.ASRecordSet; import railo.runtime.Component; import railo.runtime.component.Property; import railo.runtime.exp.ApplicationException; import railo.runtime.exp.PageException; import railo.runtime.op.Caster; import railo.runtime.op.Decision; import railo.runtime.type.Query; import railo.runtime.type.QueryColumn; import railo.runtime.type.QueryImpl; import railo.runtime.type.UDF; import railo.runtime.type.cfc.ComponentAccess; import flashgateway.io.ASObject; /** * Cast a CFML object to AMF Objects and the other way */ public final class OpenAMFCaster implements AMFCaster { private static OpenAMFCaster singelton; private OpenAMFCaster(){} public static AMFCaster getInstance(){ if(singelton==null){ singelton= new OpenAMFCaster(); } return singelton; } /** * cast cfml Object to AMF Object * @param o * @return * @throws PageException */ public Object toAMFObject(Object o) throws PageException { if(o instanceof ASObject) return o; if(Decision.isBinary(o)) return o; if(Decision.isArray(o)) return toAMFObject(Caster.toList(o,true)); if(Decision.isBoolean(o)) return Caster.toBoolean(o); if(Decision.isComponent(o)) return toAMFObject((Component)o); if(Decision.isDateSimple(o,false))return Caster.toDate(o,null); if(Decision.isNumeric(o)) return Caster.toDouble(o); if(Decision.isQuery(o)) return toAMFObject(Caster.toQuery(o)); if(Decision.isStruct(o)) return toAMFObject(Caster.toMap(o,true)); if(Decision.isUserDefinedFunction(o)) return toAMFObject((UDF)o); return o; } private List toAMFObject(List list) throws PageException { ListIterator it = list.listIterator(); while(it.hasNext()) { list.set(it.nextIndex(),toAMFObject(it.next())); } return list; } private Map toAMFObject(Map map) throws PageException { Object[] keys = map.keySet().toArray(); for(int i=0;i<keys.length;i++) { Object key=keys[i]; Object value=map.get(key); if(key instanceof String) { map.remove(key); key=((String)key).toUpperCase(); } map.put(key,toAMFObject(value)); } return map; } private Object toAMFObject(Component c) throws PageException { ASObject aso = new ASObject(); if(c instanceof ComponentAccess) { Property[] prop = c.getProperties(false); if(prop!=null)for(int i=0;i<prop.length;i++) { aso.put(prop[i].getName().toUpperCase(), toAMFObject(c.get(prop[i].getName(),null))); } } return aso; } private ASRecordSet toAMFObject(Query qry) throws PageException { PageableRecordsetConfig prsc = new PageableRecordsetConfig(); prsc.setInitialDataRowCount(qry.getRowCount()); OpenAMFConfig.getInstance().setPageableRecordsetConfig(prsc); ASRecordSet rs=new ASRecordSet(); String[] keys=qry.getColumns(); QueryColumn[] columns=new QueryColumn[keys.length]; for(int i=0;i<columns.length;i++) { columns[i]=qry.getColumn(keys[i]); //rows.add(i,new ArrayList()); } int iCol; ArrayList rows = new ArrayList(); ArrayList row; int rowCount=qry.getRecordcount(); for(int iRow=1;iRow<=rowCount;iRow++) { rows.add(row=new ArrayList()); for(iCol=0;iCol<columns.length;iCol++) { row.add(toAMFObject(columns[iCol].get(iRow,null))); } } rs.populate(qry.getColumns(),rows); return rs; } private static Object toAMFObject(UDF udf) throws PageException { throw new ApplicationException("can't send a User Defined Function ("+udf.getFunctionName()+") via flash remoting"); } public Object toCFMLObject(Object amf) throws PageException { if(amf instanceof List) return toCFMLObject((List)amf); if(amf instanceof Map) return toCFMLObject((Map)amf); if(amf instanceof ASRecordSet) return toCFMLObject((ASRecordSet)amf); return amf; } private List toCFMLObject(List list) throws PageException { ListIterator it = list.listIterator(); while(it.hasNext()) { list.set(it.nextIndex(),toCFMLObject(it.next())); } return list; } private Map toCFMLObject(Map map) throws PageException { Object[] keys = map.keySet().toArray(); for(int i=0;i<keys.length;i++) { Object key=keys[i]; map.put(key,toCFMLObject(map.get(key))); } return map; } private Query toCFMLObject(ASRecordSet rs) throws PageException { String[] columns = rs.getColumnNames(); List rows = rs.rows(); int len=0; if(rows.size()>0) len=((List)rows.get(0)).size(); Query qry=new QueryImpl(columns,len,"query"); List row; for(int iCol=0;iCol<columns.length;iCol++) { row=(List) rows.get(iCol); QueryColumn column = qry.getColumn(columns[iCol]); for(int iRow=0;iRow<row.size();iRow++) { column.set(iRow+1,toCFMLObject(row.get(iRow))); } } return qry; } /** * translate a AMFBody type to a String type * @param type * @return string type */ public static String toStringType(byte type) { switch(type) { case AMFBody.DATA_TYPE_ARRAY: return "array"; case AMFBody.DATA_TYPE_AS_OBJECT: return "as object"; case AMFBody.DATA_TYPE_BOOLEAN: return "boolean"; case AMFBody.DATA_TYPE_CUSTOM_CLASS: return "custom"; case AMFBody.DATA_TYPE_DATE: return "date"; case AMFBody.DATA_TYPE_LONG_STRING: return "long string"; case AMFBody.DATA_TYPE_MIXED_ARRAY: return "mixed array"; case AMFBody.DATA_TYPE_MOVIE_CLIP: return "movie"; case AMFBody.DATA_TYPE_NULL: return "null"; case AMFBody.DATA_TYPE_NUMBER: return "number"; case AMFBody.DATA_TYPE_OBJECT: return "object"; case AMFBody.DATA_TYPE_OBJECT_END: return "object end"; case AMFBody.DATA_TYPE_RECORDSET: return "recordset"; case AMFBody.DATA_TYPE_REFERENCE_OBJECT: return "ref object"; case AMFBody.DATA_TYPE_STRING: return "string"; case AMFBody.DATA_TYPE_UNDEFINED: return "undefined"; case AMFBody.DATA_TYPE_UNKNOWN: return "unknow"; case AMFBody.DATA_TYPE_XML: return "xml"; } return ""; } public void init(Map arguments) { // TODO Auto-generated method stub } }