001    package railo.runtime.net.rpc;
002    
003    import java.math.BigDecimal;
004    import java.util.ArrayList;
005    import java.util.Calendar;
006    import java.util.Date;
007    import java.util.HashMap;
008    import java.util.HashSet;
009    import java.util.Iterator;
010    import java.util.Map;
011    import java.util.Set;
012    import java.util.Map.Entry;
013    import java.util.TimeZone;
014    import java.util.Vector;
015    
016    import javax.xml.namespace.QName;
017    import javax.xml.rpc.encoding.TypeMapping;
018    
019    import org.apache.axis.Constants;
020    import org.apache.axis.types.Day;
021    import org.apache.axis.types.Duration;
022    import org.apache.axis.types.Entities;
023    import org.apache.axis.types.Entity;
024    import org.apache.axis.types.Language;
025    import org.apache.axis.types.Month;
026    import org.apache.axis.types.MonthDay;
027    import org.apache.axis.types.NCName;
028    import org.apache.axis.types.NMToken;
029    import org.apache.axis.types.NMTokens;
030    import org.apache.axis.types.Name;
031    import org.apache.axis.types.Token;
032    import org.apache.axis.types.URI;
033    import org.apache.axis.types.URI.MalformedURIException;
034    import org.apache.axis.types.Year;
035    import org.apache.axis.types.YearMonth;
036    
037    import railo.commons.lang.ClassException;
038    import railo.commons.lang.ClassUtil;
039    import railo.commons.lang.StringUtil;
040    import railo.runtime.Component;
041    import railo.runtime.ComponentScope;
042    import railo.runtime.ComponentWrap;
043    import railo.runtime.PageContext;
044    import railo.runtime.component.Property;
045    import railo.runtime.engine.ThreadLocalPageContext;
046    import railo.runtime.exp.ExpressionException;
047    import railo.runtime.exp.PageException;
048    import railo.runtime.interpreter.CFMLExpressionInterpreter;
049    import railo.runtime.op.Caster;
050    import railo.runtime.op.Decision;
051    import railo.runtime.op.date.DateCaster;
052    import railo.runtime.reflection.Reflector;
053    import railo.runtime.type.Array;
054    import railo.runtime.type.Collection;
055    import railo.runtime.type.Query;
056    import railo.runtime.type.QueryColumn;
057    import railo.runtime.type.QueryImpl;
058    import railo.runtime.type.Struct;
059    import railo.runtime.type.StructImpl;
060    import railo.runtime.type.UDF;
061    import railo.runtime.type.cfc.ComponentAccess;
062    import railo.runtime.type.dt.DateTime;
063    import railo.runtime.type.dt.TimeSpan;
064    import railo.runtime.type.scope.Argument;
065    import railo.runtime.type.util.ArrayUtil;
066    import railo.runtime.type.util.ComponentUtil;
067    import coldfusion.xml.rpc.QueryBean;
068    
069    /**
070     * Axis Type Caster
071     */
072    public final class AxisCaster {
073    
074            /**
075         * cast a value to a Axis Compatible Type
076         * @param type
077         * @param value
078         * @return Axis Compatible Type
079         * @throws PageException
080         */
081        public static Object toAxisType(TypeMapping tm,TimeZone tz,QName type, Object value, Class targetClass) throws PageException {
082                    return _toAxisType(tm, tz, type, value, targetClass,new HashSet<Object>());
083            }
084    
085        public static Object toAxisType(TypeMapping tm,Object value,Class targetClass) throws PageException {
086            return _toAxisType(tm,null,null, value, targetClass, new HashSet<Object>());
087        }
088            
089        /**
090         * cast a value to a Axis Compatible Type
091         * @param type
092         * @param value
093         * @return Axis Compatible Type
094         * @throws PageException
095         */
096        private static Object _toAxisType(TypeMapping tm,TimeZone tz,QName type, Object value, Class targetClass,Set<Object> done) throws PageException {
097            if(done.contains(value)){
098                            return null;// TODO not sure what in this case is the best solution.
099                    }
100            
101                    done.add(value);
102            try{
103            
104                    if(type!=null) {
105                            // XSD
106                            for(int i=0;i<Constants.URIS_SCHEMA_XSD.length;i++) {
107                                if(Constants.URIS_SCHEMA_XSD[i].equals(type.getNamespaceURI())) {
108                                    return toAxisTypeXSD(tm,tz,type, value,targetClass,done);
109                                }
110                            }
111                            //SOAP
112                            if(type.getNamespaceURI().indexOf("soap")!=-1) {
113                                return toAxisTypeSoap(tm,type, value,targetClass,done);
114                            }
115                            // Specials
116                            if(type.getLocalPart().equals("ArrayOf_xsd_anyType"))
117                                return toArrayList(tm,value,targetClass,done);
118                    }
119                    return _toAxisTypeSub(tm,value,targetClass,done);
120            
121            }
122            finally{
123                    done.remove(value);
124            }
125        }
126        
127        private static Object toAxisTypeSoap(TypeMapping tm,QName type, Object value, Class targetClass, Set<Object> done) throws PageException {
128            String local = type.getLocalPart();
129            
130            if(local.equals(Constants.SOAP_ARRAY.getLocalPart())) return toArrayList(tm,value,targetClass,done);
131            if(local.equals(Constants.SOAP_ARRAY12.getLocalPart())) return toArrayList(tm,value,targetClass,done);
132            if(local.equals(Constants.SOAP_ARRAY_ATTRS11.getLocalPart())) return toArrayList(tm,value,targetClass,done);
133            if(local.equals(Constants.SOAP_ARRAY_ATTRS12.getLocalPart())) return toArrayList(tm,value,targetClass,done);
134            if(local.equals(Constants.SOAP_BASE64.getLocalPart())) return Caster.toBinary(value);
135            if(local.equals(Constants.SOAP_BASE64BINARY.getLocalPart())) return Caster.toBinary(value);
136            if(local.equals(Constants.SOAP_BOOLEAN.getLocalPart())) return Caster.toBoolean(value);
137            if(local.equals(Constants.SOAP_BYTE.getLocalPart())) return Caster.toByte(value);
138            if(local.equals(Constants.SOAP_DECIMAL.getLocalPart())) return new BigDecimal(Caster.toDoubleValue(value));
139            if(local.equals(Constants.SOAP_DOUBLE.getLocalPart())) return Caster.toDouble(value);
140            if(local.equals(Constants.SOAP_FLOAT.getLocalPart())) return new Float(Caster.toDoubleValue(value));
141            if(local.equals(Constants.SOAP_INT.getLocalPart())) return Caster.toInteger(value);
142            if(local.equals(Constants.SOAP_INTEGER.getLocalPart())) return Caster.toInteger(value);
143            if(local.equals(Constants.SOAP_LONG.getLocalPart())) return Caster.toLong(value);
144            if(local.equals(Constants.SOAP_MAP.getLocalPart())) return toMap(tm,value,targetClass,done);
145            if(local.equals(Constants.SOAP_SHORT.getLocalPart())) return Caster.toShort(value);
146            if(local.equals(Constants.SOAP_STRING.getLocalPart())) return Caster.toString(value);
147            if(local.equals(Constants.SOAP_VECTOR.getLocalPart())) return toVector(tm,value,targetClass,done);
148            
149            // TODO SOAP_COMMON_ATTRS11, SOAP_COMMON_ATTRS12, SOAP_DOCUMENT, SOAP_ELEMENT
150            return _toAxisTypeSub(tm,value,targetClass,done);
151            
152            
153        }
154    
155        private static Object toAxisTypeXSD(TypeMapping tm,TimeZone tz,QName type, Object value, Class targetClass, Set<Object> done) throws PageException {
156            String local = type.getLocalPart();
157            if(local.equals(Constants.XSD_ANYSIMPLETYPE.getLocalPart())) return Caster.toString(value);
158            if(local.equals(Constants.XSD_ANYURI.getLocalPart())) return toURI(value);
159            if(local.equals(Constants.XSD_STRING.getLocalPart())) return Caster.toString(value);
160            if(local.equals(Constants.XSD_BASE64.getLocalPart())) return Caster.toBinary(value);
161            if(local.equals(Constants.XSD_BOOLEAN.getLocalPart())) return Caster.toBoolean(value);
162            if(local.equals(Constants.XSD_BYTE.getLocalPart())) return Caster.toByte(value);
163            if(local.equals(Constants.XSD_DATE.getLocalPart())) return Caster.toDate(value,null);
164            if(local.equals(Constants.XSD_DATETIME.getLocalPart())) return Caster.toDate(value,null);
165            if(local.equals(Constants.XSD_DAY.getLocalPart())) return toDay(value);
166            if(local.equals(Constants.XSD_DECIMAL.getLocalPart())) return new BigDecimal(Caster.toDoubleValue(value));
167            if(local.equals(Constants.XSD_DOUBLE.getLocalPart())) return Caster.toDouble(value);
168            if(local.equals(Constants.XSD_DURATION.getLocalPart())) return toDuration(value);
169            if(local.equals(Constants.XSD_ENTITIES.getLocalPart())) return toEntities(value);
170            if(local.equals(Constants.XSD_ENTITY.getLocalPart())) return toEntity(value);
171            if(local.equals(Constants.XSD_FLOAT.getLocalPart())) return new Float(Caster.toDoubleValue(value));
172            if(local.equals(Constants.XSD_HEXBIN.getLocalPart())) return Caster.toBinary(value);
173            if(local.equals(Constants.XSD_ID.getLocalPart())) return Caster.toString(value);
174            if(local.equals(Constants.XSD_IDREF.getLocalPart())) return Caster.toString(value);
175            if(local.equals(Constants.XSD_IDREFS.getLocalPart())) return Caster.toString(value);
176            if(local.equals(Constants.XSD_INT.getLocalPart())) return Caster.toInteger(value);
177            if(local.equals(Constants.XSD_INTEGER.getLocalPart())) return Caster.toInteger(value);
178            if(local.equals(Constants.XSD_LANGUAGE.getLocalPart())) return toLanguage(value);
179            if(local.equals(Constants.XSD_LONG.getLocalPart())) return Caster.toLong(value);
180            if(local.equals(Constants.XSD_MONTH.getLocalPart())) return toMonth(value);
181            if(local.equals(Constants.XSD_MONTHDAY.getLocalPart())) return toMonthDay(value);
182            if(local.equals(Constants.XSD_NAME.getLocalPart())) return toName(value);
183            if(local.equals(Constants.XSD_NCNAME.getLocalPart())) return toNCName(value);
184            if(local.equals(Constants.XSD_NEGATIVEINTEGER.getLocalPart())) return Caster.toInteger(value);
185            if(local.equals(Constants.XSD_NMTOKEN.getLocalPart())) return toNMToken(value);
186            if(local.equals(Constants.XSD_NMTOKENS.getLocalPart())) return toNMTokens(value);
187            if(local.equals(Constants.XSD_NONNEGATIVEINTEGER.getLocalPart())) return Caster.toInteger(value);
188            if(local.equals(Constants.XSD_NONPOSITIVEINTEGER.getLocalPart())) return Caster.toInteger(value);
189            if(local.equals(Constants.XSD_NORMALIZEDSTRING.getLocalPart())) return Caster.toString(value);
190            if(local.equals(Constants.XSD_POSITIVEINTEGER.getLocalPart())) return Caster.toInteger(value);
191            if(local.equals(Constants.XSD_QNAME.getLocalPart())) return toQName(value);
192            if(local.equals(Constants.XSD_SCHEMA.getLocalPart())) return toQName(value);
193            if(local.equals(Constants.XSD_SHORT.getLocalPart())) return Caster.toShort(value);
194            if(local.equals(Constants.XSD_TIME.getLocalPart())) return DateCaster.toTime(tz,value);
195            if(local.equals(Constants.XSD_TIMEINSTANT1999.getLocalPart())) return DateCaster.toTime(tz,value);
196            if(local.equals(Constants.XSD_TIMEINSTANT2000.getLocalPart())) return DateCaster.toTime(tz,value);
197            if(local.equals(Constants.XSD_TOKEN.getLocalPart())) return toToken(value);
198            if(local.equals(Constants.XSD_UNSIGNEDBYTE.getLocalPart())) return Caster.toByte(value);
199            if(local.equals(Constants.XSD_UNSIGNEDINT.getLocalPart())) return Caster.toInteger(value);
200            if(local.equals(Constants.XSD_UNSIGNEDLONG.getLocalPart())) return Caster.toLong(value);
201            if(local.equals(Constants.XSD_UNSIGNEDSHORT.getLocalPart())) return Caster.toShort(value);
202            if(local.equals(Constants.XSD_YEAR.getLocalPart())) return toYear(value);
203            if(local.equals(Constants.XSD_YEARMONTH.getLocalPart())) return toYearMonth(value);
204            return _toAxisTypeSub(tm,value,targetClass,done);
205        }
206    
207        private static ArrayList<Object> toArrayList(TypeMapping tm,Object value, Class targetClass, Set<Object> done) throws PageException {
208            Array arr = Caster.toArray(value);
209            ArrayList<Object> al=new ArrayList<Object>();
210            int len=arr.size();
211            Object o;
212            for(int i=0;i<len;i++) {
213                o=arr.get(i+1,null);
214                al.add(i,_toAxisType(tm,null,null,o,targetClass,done));
215            }
216            return al;
217        }
218        private static Object[] toNativeArray(TypeMapping tm,Object value,Class targetClass, Set<Object> done) throws PageException {
219            Object[] objs = Caster.toNativeArray(value);
220            Object[] rtns;
221            Class componentType = null;
222            if(targetClass!=null) {
223                    componentType = targetClass.getComponentType();
224            }
225            
226            if(componentType!=null) 
227                    rtns = (Object[]) java.lang.reflect.Array.newInstance(componentType, objs.length);
228            else 
229                    rtns = new Object[objs.length];
230            
231            for(int i=0;i<objs.length;i++) {
232                    rtns[i]=_toAxisType(tm,null,null,objs[i],componentType,done);
233            }
234            return rtns;
235        }
236    
237        private static Vector<Object> toVector(TypeMapping tm,Object value, Class targetClass, Set<Object> done) throws PageException {
238            Array arr = Caster.toArray(value);
239            Vector<Object> v=new Vector<Object>();
240            int len=arr.size();
241            Object o;
242            for(int i=0;i<len;i++) {
243                o=arr.get(i+1,null);
244                v.set(i,_toAxisType(tm,null,null,o,targetClass,done));
245            }
246            return v;
247        }
248    
249        private static Object toPojo(TypeMapping tm,Component comp, Class targetClass, Set<Object> done) throws PageException {
250    
251            PageContext pc = ThreadLocalPageContext.get(); 
252            
253                try {
254                    return _toPojo(pc, tm, comp,targetClass,done);
255                            
256                    }
257                    catch (Exception e) {
258                            throw Caster.toPageException(e);
259                    }
260                    /*finally {
261                            //pc.removeLastPageSource(true);
262                    }*/
263        }
264        
265        private static Object _toPojo(PageContext pc, TypeMapping tm,Component comp, Class targetClass, Set<Object> done) throws PageException {//print.ds();System.exit(0);
266            ComponentAccess ca = ComponentUtil.toComponentAccess(comp);
267            comp=ComponentWrap.toComponentWrap(Component.ACCESS_PRIVATE,ca);
268                    ComponentScope scope = ca.getComponentScope();
269            
270            Property[] props=ComponentUtil.getProperties(comp,false);
271            //Map rtn=new HashTable();
272            Object obj=null;
273                    try {
274                            obj = ClassUtil.loadInstance(ComponentUtil.getServerComponentPropertiesClass(comp));
275                    } catch (ClassException e) {
276                            throw Caster.toPageException(e);
277                    }
278            
279            //PageContext pc = ThreadLocalPageContext.get();
280            Property p;
281            Object v;
282            Collection.Key k;
283                    CFMLExpressionInterpreter interpreter = new CFMLExpressionInterpreter();
284            for(int i=0;i<props.length;i++){
285                    p=props[i];
286                    k=Caster.toKey(p.getName());
287            // value
288                    v=scope.get(k,null);
289                    if(v==null)v=comp.get(k, null);
290            // default
291                    
292                    if(v!=null)v=Caster.castTo(pc, p.getType(), v, false);
293                    else{
294                            if(!StringUtil.isEmpty(p.getDefault())){
295                                    try {
296                                            v=Caster.castTo(pc, p.getType(), p.getDefault(), false);
297                                            
298                                    }
299                                    catch(PageException pe) {
300                                            try {
301                                                    v=interpreter.interpret(pc, p.getDefault());
302                                                    v=Caster.castTo(pc, p.getType(), v, false);
303                                            }
304                                    catch(PageException pe2) {
305                                                    throw new ExpressionException("can not use default value ["+p.getDefault()+"] for property ["+p.getName()+"] with type ["+p.getType()+"]");
306                                    }
307                                    }
308                            }
309                    }
310                    
311            // set or throw
312                    if(v==null) {
313                            if(p.isRequired())throw new ExpressionException("required property ["+p.getName()+"] is not defined");
314                    }
315                    else {
316                            Reflector.callSetter(obj, p.getName().toLowerCase(), _toAxisType(tm,null,null,v,targetClass,done));     
317                    }
318            }
319            return obj;
320        }
321        
322        private static QueryBean toQueryBean(TypeMapping tm,Object value, Class targetClass, Set<Object> done) throws PageException {
323            Query query = Caster.toQuery(value);
324                    int recordcount=query.getRecordcount();
325            String[] columnList = query.getColumns();
326            QueryColumn[] columns=new QueryColumn[columnList.length];
327            Object[][] data = new Object[recordcount][columnList.length];
328            
329            for(int i=0;i<columnList.length;i++) {
330                    columns[i]=query.getColumn(columnList[i]);
331            }
332            
333            int row;
334            for(row=1;row<=recordcount;row++) {
335                for(int i=0;i<columns.length;i++) {
336                    data[row-1][i]=_toAxisType(tm,null,null,columns[i].get(row),targetClass,done);
337                }
338            }
339            
340            QueryBean qb = new QueryBean();
341            qb.setColumnList(columnList);
342            qb.setData(data);
343            return qb;
344            
345        }
346        
347    
348        
349        private static Map<String,Object> toMap(TypeMapping tm,Object value, Class targetClass, Set<Object> done) throws PageException {
350            Struct src = Caster.toStruct(value);
351            Map<String,Object> trg=new HashMap<String,Object>();
352            String[] keys = src.keysAsString();
353            for(int i=0;i<keys.length;i++) {
354                trg.put(keys[i],_toAxisType(tm,null,null,src.get(keys[i],null),targetClass,done));
355            }
356            return trg;
357            
358        }
359    
360        private static Object _toAxisTypeSub(TypeMapping tm,Object value,Class targetClass,Set<Object> done) throws PageException {
361            // Date
362            if(value instanceof Date) {// not set to Decision.isDate(value)
363                    return new Date(((Date)value).getTime());
364            }
365            
366            // Array
367            if(Decision.isArray(value) && !(value instanceof Argument)) {
368                    if(value instanceof byte[]) return value;
369                    return toNativeArray(tm,value,targetClass,done);
370            }
371            // Struct
372            if(Decision.isStruct(value)) {
373                    if(value instanceof Component) {
374                            Object pojo= toPojo(tm,(Component)value,targetClass,done);
375                            try     {       
376                                    QName name = new QName("http://rpc.xml.coldfusion",pojo.getClass().getName());
377                                    TypeMappingUtil.registerBeanTypeMapping(tm, pojo.getClass(), name);
378                                    
379                            }
380                            catch(Throwable fault){
381                                    throw Caster.toPageException(fault);
382                            }
383                            return pojo;
384                    }
385                    return toMap(tm,value,targetClass,done);
386            }
387            // Query
388            if(Decision.isQuery(value)) return toQueryBean(tm,value,targetClass,done);
389            // Other
390            return value;
391        }
392        
393        public static Class toAxisTypeClass(Class clazz) {
394            if(Query.class==clazz) return QueryBean.class;
395            if(Array.class==clazz) return Object[].class;
396            if(Struct.class==clazz) return Map.class;
397            return clazz;
398        }
399        
400        private static Object toURI(Object value) throws PageException {
401            if(value instanceof URI) return value;
402            if(value instanceof java.net.URI) return value;
403            try {
404                return new URI(Caster.toString(value));
405            } catch (MalformedURIException e) {
406                throw Caster.toPageException(e);
407            }
408        }
409    
410        private static Token toToken(Object value) throws PageException {
411            if(value instanceof Token) return (Token) value;
412            return new Token(Caster.toString(value));
413        }
414        
415        private static QName toQName(Object value) throws PageException {
416            if(value instanceof QName) return (QName) value;
417            return new QName(Caster.toString(value));
418        }
419    
420        private static NMTokens toNMTokens(Object value) throws PageException {
421            if(value instanceof NMTokens) return (NMTokens) value;
422            return new NMTokens(Caster.toString(value));
423        }
424        
425        private static NMToken toNMToken(Object value) throws PageException {
426            if(value instanceof NMToken) return (NMToken) value;
427            return new NMToken(Caster.toString(value));
428        }
429        private static NCName toNCName(Object value) throws PageException {
430            if(value instanceof NCName) return (NCName) value;
431            return new NCName(Caster.toString(value));
432        }
433    
434        private static Name toName(Object value) throws PageException {
435            if(value instanceof Name) return (Name) value;
436            return new Name(Caster.toString(value));
437        }
438    
439        private static Language toLanguage(Object value) throws PageException {
440            if(value instanceof Language) return (Language) value;
441            return new Language(Caster.toString(value));
442        }
443    
444        private static Entities toEntities(Object value) throws PageException {
445            if(value instanceof Entities) return (Entities) value;
446            return new Entities(Caster.toString(value));
447        }
448        
449        private static Entity toEntity(Object value) throws PageException {
450            if(value instanceof Entity) return (Entity) value;
451            return new Entity(Caster.toString(value));
452        }
453    
454        private static Day toDay(Object value) throws PageException {
455            if(value instanceof Day) return (Day) value;
456            if(Decision.isDateSimple(value,false)) {
457                return new Day(Caster.toDate(value,null).getDate());
458            }
459            
460            try {
461                return new Day(Caster.toIntValue(value));
462            } 
463            catch (Exception e) {
464                try {
465                    return new Day(Caster.toString(value));
466                } catch (NumberFormatException nfe) {
467                    throw Caster.toPageException(nfe);
468                } 
469                catch (ExpressionException ee) {
470                    throw ee;
471                }
472            }
473        }
474    
475        private static Year toYear(Object value) throws PageException {
476            if(value instanceof Year) return (Year) value;
477            if(Decision.isDateSimple(value,false)) {
478                return new Year(Caster.toDate(value,null).getYear());
479            }
480            try {
481                return new Year(Caster.toIntValue(value));
482            } 
483            catch (Exception e) {
484                try {
485                    return new Year(Caster.toString(value));
486                } catch (NumberFormatException nfe) {
487                    throw Caster.toPageException(nfe);
488                } 
489                catch (ExpressionException ee) {
490                    throw ee;
491                }
492            }
493        }
494    
495        private static Month toMonth(Object value) throws PageException {
496            if(value instanceof Month) return (Month) value;
497            if(Decision.isDateSimple(value,false)) {
498                return new Month(Caster.toDate(value,null).getMonth());
499            }
500            try {
501                return new Month(Caster.toIntValue(value));
502            } 
503            catch (Exception e) {
504                try {
505                    return new Month(Caster.toString(value));
506                } catch (NumberFormatException nfe) {
507                    throw Caster.toPageException(nfe);
508                } 
509                catch (ExpressionException ee) {
510                    throw ee;
511                }
512            }
513        }
514    
515        private static YearMonth toYearMonth(Object value) throws PageException {
516            if(value instanceof YearMonth) return (YearMonth) value;
517            if(Decision.isDateSimple(value,false)) {
518                DateTime dt = Caster.toDate(value,null);
519                return new YearMonth(dt.getYear(),dt.getMonth());
520            }
521            
522            try {
523                return new YearMonth(Caster.toString(value));
524            } catch (NumberFormatException nfe) {
525                throw Caster.toPageException(nfe);
526            } 
527            catch (ExpressionException ee) {
528                throw ee;
529            }
530        }
531    
532        private static MonthDay toMonthDay(Object value) throws PageException {
533            if(value instanceof MonthDay) return (MonthDay) value;
534            if(Decision.isDateSimple(value,false)) {
535                DateTime dt = Caster.toDate(value,null);
536                return new MonthDay(dt.getMonth(),dt.getDate());
537            }
538            
539            try {
540                return new MonthDay(Caster.toString(value));
541            } catch (NumberFormatException nfe) {
542                throw Caster.toPageException(nfe);
543            } 
544            catch (ExpressionException ee) {
545                throw ee;
546            }
547        }
548    
549        private static Duration toDuration(Object value) throws PageException, IllegalArgumentException {
550            if(value instanceof Duration) return (Duration) value;
551            try {
552                TimeSpan ts = Caster.toTimespan(value);
553                return new Duration(true, 0, 0, ts.getDay(), ts.getHour(), ts.getMinute(), ts.getSecond());
554            } catch (PageException e) {
555                return new Duration(Caster.toString(value));
556            }
557        }
558    
559        public static Object toRailoType(PageContext pc, Object value) throws PageException {
560            pc=ThreadLocalPageContext.get(pc);
561            if(pc!=null && value instanceof Pojo) {
562                    try{
563                            ComponentAccess c = ComponentUtil.toComponentAccess(pc.loadComponent(value.getClass().getName()));
564                            ComponentWrap cw=ComponentWrap.toComponentWrap(Component.ACCESS_PRIVATE,c);
565                    
566                            // delete this scope data members
567                            Collection.Key[] keys = cw.keys();
568                            Object member;
569                            for(int i=0;i<keys.length;i++) {
570                                    member = cw.get(keys[i]);
571                                    if(member instanceof UDF) continue;
572                        cw.removeEL(keys[i]);
573                            }
574                            
575                            
576                            Property[] props = c.getProperties(false);
577                            Property prop;
578                            for(int i=0;i<props.length;i++){
579                                    prop=props[i];
580                                    try{
581                                            cw.set(pc, prop.getName(), toRailoType(pc,Reflector.callGetter(value, prop.getName())));
582                                    }
583                                    catch(PageException pe){
584                                            pe.printStackTrace();
585                                    }
586                            }
587                            return c;
588                    }
589                    catch(Throwable t){
590                            return value;
591                    }
592            }
593            if(value instanceof Date || value instanceof Calendar) {// do not change to caster.isDate
594                    return Caster.toDate(value,null);
595            }
596            if(value instanceof Object[]) {
597                    Object[] arr=(Object[]) value;
598                    if(!ArrayUtil.isEmpty(arr)){
599                            boolean allTheSame=true;
600                            // byte
601                            if(arr[0] instanceof Byte){
602                                    for(int i=1;i<arr.length;i++){
603                                            if(!(arr[i] instanceof Byte)){
604                                                    allTheSame=false;
605                                                    break;
606                                            }
607                                    }
608                                    if(allTheSame){
609                                            byte[] bytes=new byte[arr.length];
610                                            for(int i=0;i<arr.length;i++){
611                                            bytes[i]=Caster.toByteValue(arr[i]);
612                                    }
613                                            return bytes;
614                                    }
615                            }
616                    }
617            }
618            if(value instanceof Byte[]) {
619                    Byte[] arr=(Byte[]) value;
620                    if(!ArrayUtil.isEmpty(arr)){
621                                    byte[] bytes=new byte[arr.length];
622                                    for(int i=0;i<arr.length;i++){
623                                    bytes[i]=arr[i].byteValue();
624                            }
625                                    return bytes;
626                    }
627            }
628            if(value instanceof byte[]) {
629                    return value;
630            }
631            if(Decision.isArray(value)) {
632                Array a = Caster.toArray(value);
633                int len=a.size();
634                Object o;
635                for(int i=1;i<=len;i++) {
636                    o=a.get(i,null);
637                    if(o!=null)a.setEL(i,toRailoType(pc,o));
638                }
639                return a;
640            }
641            if(value instanceof Map) {
642                    Struct sct = new StructImpl();
643                Iterator it=((Map)value).entrySet().iterator();
644                Map.Entry entry;
645                while(it.hasNext()) {
646                    entry=(Entry) it.next();
647                    sct.setEL(Caster.toString(entry.getKey()),toRailoType(pc,entry.getValue()));
648                }
649                return sct;
650                    
651                    
652                    //return StructUtil.copyToStruct((Map)value);
653            }
654            if(isQueryBean(value)) {
655                    QueryBean qb = (QueryBean) value;
656                String[] strColumns = qb.getColumnList();
657                Object[][] data = qb.getData();
658                int recorcount=data.length;
659                Query qry=new QueryImpl(strColumns,recorcount,"QueryBean");
660                QueryColumn[] columns=new QueryColumn[strColumns.length];
661                for(int i=0;i<columns.length;i++) {
662                    columns[i]=qry.getColumn(strColumns[i]);
663                }
664                
665                int row;
666                for(row=1;row<=recorcount;row++) {
667                    for(int i=0;i<columns.length;i++) {
668                            columns[i].set(row,toRailoType(pc,data[row-1][i]));
669                    }
670                }
671                return qry;
672            }
673            if(Decision.isQuery(value)) {
674                Query q = Caster.toQuery(value);
675                int recorcount=q.getRecordcount();
676                String[] strColumns = q.getColumns();
677                
678                QueryColumn col;
679                int row;
680                for(int i=0;i<strColumns.length;i++) {
681                    col=q.getColumn(strColumns[i]);
682                    for(row=1;row<=recorcount;row++) {
683                        col.set(row,toRailoType(pc,col.get(row)));
684                    }
685                }
686                return q;
687            }
688            return value;
689        }
690    
691            private static boolean isQueryBean(Object value) {
692                    return (value instanceof QueryBean);
693            }
694    
695    
696    }