/** * Copyright (c) 2014, the Railo Company Ltd. * Copyright (c) 2015, Lucee Assosication Switzerland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ package lucee.runtime.net.rpc; import java.io.IOException; import java.math.BigDecimal; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TimeZone; import java.util.Vector; import javax.xml.namespace.QName; import javax.xml.rpc.encoding.TypeMapping; import lucee.commons.lang.ClassException; import lucee.commons.lang.ClassUtil; import lucee.commons.lang.ExceptionUtil; import lucee.commons.lang.Pair; import lucee.commons.lang.PhysicalClassLoader; import lucee.commons.lang.StringUtil; import lucee.runtime.Component; import lucee.runtime.ComponentScope; import lucee.runtime.ComponentSpecificAccess; import lucee.runtime.PageContext; import lucee.runtime.component.Property; import lucee.runtime.component.PropertyImpl; import lucee.runtime.engine.ThreadLocalPageContext; import lucee.runtime.exp.ApplicationException; import lucee.runtime.exp.ExpressionException; import lucee.runtime.exp.PageException; import lucee.runtime.interpreter.CFMLExpressionInterpreter; import lucee.runtime.net.http.ReqRspUtil; import lucee.runtime.op.Caster; import lucee.runtime.op.Decision; import lucee.runtime.op.date.DateCaster; import lucee.runtime.reflection.Reflector; import lucee.runtime.type.Array; import lucee.runtime.type.Collection; import lucee.runtime.type.Collection.Key; import lucee.runtime.type.KeyImpl; import lucee.runtime.type.ObjectWrap; import lucee.runtime.type.Query; import lucee.runtime.type.QueryColumn; import lucee.runtime.type.QueryImpl; import lucee.runtime.type.Struct; import lucee.runtime.type.StructImpl; import lucee.runtime.type.dt.DateTime; import lucee.runtime.type.dt.TimeSpan; import lucee.runtime.type.scope.Argument; import lucee.runtime.type.util.ArrayUtil; import lucee.runtime.type.util.ComponentUtil; import org.apache.axis.Constants; import org.apache.axis.types.Day; import org.apache.axis.types.Duration; import org.apache.axis.types.Entities; import org.apache.axis.types.Entity; import org.apache.axis.types.Language; import org.apache.axis.types.Month; import org.apache.axis.types.MonthDay; import org.apache.axis.types.NCName; import org.apache.axis.types.NMToken; import org.apache.axis.types.NMTokens; import org.apache.axis.types.Name; import org.apache.axis.types.Token; import org.apache.axis.types.URI; import org.apache.axis.types.URI.MalformedURIException; import org.apache.axis.types.Year; import org.apache.axis.types.YearMonth; import org.apache.axis.wsdl.symbolTable.TypeEntry; import coldfusion.xml.rpc.QueryBean; /** * Axis Type Caster */ public final class AxisCaster { /** * cast a value to a Axis Compatible Type * @param type * @param value * @return Axis Compatible Type * @throws PageException */ public static Object toAxisType(TypeMapping tm,TimeZone tz,TypeEntry typeEntry,QName type, Object value) throws PageException { return _toAxisType(tm, tz, typeEntry,type,null, value,new HashSet<Object>()); } public static Object toAxisType(TypeMapping tm,Object value, Class targetClass) throws PageException { return _toAxisType(tm,null,null,null,targetClass, value, new HashSet<Object>()); } /** * cast a value to a Axis Compatible Type * @param type * @param value * @return Axis Compatible Type * @throws PageException */ private static Object _toAxisType(TypeMapping tm,TimeZone tz,TypeEntry typeEntry,QName type, Class targetClass, Object value,Set<Object> done) throws PageException { // first make sure we have no wrapper if(value instanceof ObjectWrap) { value=((ObjectWrap)value).getEmbededObject(); } if(done.contains(value)){ return null;// TODO not sure what in this case is the best solution. } done.add(value); try{ if(type!=null) { // Array Of if(type.getLocalPart().startsWith("ArrayOf")) { return toArray(tm,typeEntry,type,value,done); } // XSD for(int i=0;i<Constants.URIS_SCHEMA_XSD.length;i++) { if(Constants.URIS_SCHEMA_XSD[i].equals(type.getNamespaceURI())) { return toAxisTypeXSD(tm,tz,type.getLocalPart(), value,done); } } if(StringUtil.startsWithIgnoreCase(type.getLocalPart(),"xsd_")) { return toAxisTypeXSD(tm,tz,type.getLocalPart().substring(4), value,done); } //SOAP if(type.getNamespaceURI().indexOf("soap")!=-1) { return toAxisTypeSoap(tm,type.getLocalPart(), value,done); } if(StringUtil.startsWithIgnoreCase(type.getLocalPart(),"soap_")) { return toAxisTypeSoap(tm,type.getLocalPart().substring(5), value,done); } } return _toDefinedType(tm,typeEntry,type,targetClass,value,done); } finally{ done.remove(value); } } private static Object toArray(TypeMapping tm, TypeEntry typeEntry,QName type, Object value, Set<Object> done) throws PageException { if(type==null || !type.getLocalPart().startsWith("ArrayOf")) throw new ApplicationException("invalid call of the functionn toArray"); // get component Type String tmp = type.getLocalPart().substring(7); QName componentType=null; // no arrayOf embeded anymore if(tmp.indexOf("ArrayOf")==-1 && typeEntry!=null) { TypeEntry ref = typeEntry.getRefType(); componentType=ref.getQName(); } if(componentType==null) { if(tmp.startsWith("_tns1_"))tmp=tmp.substring(6); componentType=new QName(type.getNamespaceURI(), tmp); } Object[] objs = Caster.toNativeArray(value); Object[] rtns; List<Object> list=new ArrayList<Object>(); Class componentClass=null; Object v; for(int i=0;i<objs.length;i++) { v=_toAxisType(tm,null,typeEntry,componentType,null,objs[i],done); list.add(v); if(i==0) { if(v!=null) componentClass=v.getClass(); } else { if(v==null || v.getClass()!=componentClass) componentClass=null; } } if(componentClass!=null) { componentClass=toAxisTypeClass(componentClass); rtns = (Object[]) java.lang.reflect.Array.newInstance(componentClass, objs.length); } else rtns = new Object[objs.length]; return list.toArray(rtns); } private static Object toAxisTypeSoap(TypeMapping tm,String local, Object value, Set<Object> done) throws PageException { if(local.equals(Constants.SOAP_ARRAY.getLocalPart())) return toArrayList(tm,value,done); if(local.equals(Constants.SOAP_ARRAY12.getLocalPart())) return toArrayList(tm,value,done); if(local.equals(Constants.SOAP_ARRAY_ATTRS11.getLocalPart())) return toArrayList(tm,value,done); if(local.equals(Constants.SOAP_ARRAY_ATTRS12.getLocalPart())) return toArrayList(tm,value,done); if(local.equals(Constants.SOAP_BASE64.getLocalPart())) return Caster.toBinary(value); if(local.equals(Constants.SOAP_BASE64BINARY.getLocalPart())) return Caster.toBinary(value); if(local.equals(Constants.SOAP_BOOLEAN.getLocalPart())) return Caster.toBoolean(value); if(local.equals(Constants.SOAP_BYTE.getLocalPart())) return Caster.toByte(value); if(local.equals(Constants.SOAP_DECIMAL.getLocalPart())) return new BigDecimal(Caster.toDoubleValue(value)); if(local.equals(Constants.SOAP_DOUBLE.getLocalPart())) return Caster.toDouble(value); if(local.equals(Constants.SOAP_FLOAT.getLocalPart())) return new Float(Caster.toDoubleValue(value)); if(local.equals(Constants.SOAP_INT.getLocalPart())) return Caster.toInteger(value); if(local.equals(Constants.SOAP_INTEGER.getLocalPart())) return Caster.toInteger(value); if(local.equals(Constants.SOAP_LONG.getLocalPart())) return Caster.toLong(value); if(local.equals(Constants.SOAP_MAP.getLocalPart())) return toMap(tm,value,done); if(local.equals(Constants.SOAP_SHORT.getLocalPart())) return Caster.toShort(value); if(local.equals(Constants.SOAP_STRING.getLocalPart())) return Caster.toString(value); if(local.equals(Constants.SOAP_VECTOR.getLocalPart())) return toVector(tm,value,done); return _toDefinedType(tm,null,null,null,value,done); } private static Object toAxisTypeXSD(TypeMapping tm,TimeZone tz,String local, Object value, Set<Object> done) throws PageException { //if(local.equals(Constants.XSD_ANY.getLocalPart())) return value; if(local.equalsIgnoreCase(Constants.XSD_ANYSIMPLETYPE.getLocalPart())) return Caster.toString(value); if(local.equalsIgnoreCase(Constants.XSD_ANYURI.getLocalPart())) return toURI(value); if(local.equalsIgnoreCase(Constants.XSD_STRING.getLocalPart())) return Caster.toString(value); if(local.equalsIgnoreCase(Constants.XSD_BASE64.getLocalPart())) return Caster.toBinary(value); if(local.equalsIgnoreCase(Constants.XSD_BOOLEAN.getLocalPart())) return Caster.toBoolean(value); if(local.equalsIgnoreCase(Constants.XSD_BYTE.getLocalPart())) return Caster.toByte(value); if(local.equalsIgnoreCase(Constants.XSD_DATE.getLocalPart())) return Caster.toDate(value,null); if(local.equalsIgnoreCase(Constants.XSD_DATETIME.getLocalPart())) return Caster.toDate(value,null); if(local.equalsIgnoreCase(Constants.XSD_DAY.getLocalPart())) return toDay(value); if(local.equalsIgnoreCase(Constants.XSD_DECIMAL.getLocalPart())) return new BigDecimal(Caster.toDoubleValue(value)); if(local.equalsIgnoreCase(Constants.XSD_DOUBLE.getLocalPart())) return Caster.toDouble(value); if(local.equalsIgnoreCase(Constants.XSD_DURATION.getLocalPart())) return toDuration(value); if(local.equalsIgnoreCase(Constants.XSD_ENTITIES.getLocalPart())) return toEntities(value); if(local.equalsIgnoreCase(Constants.XSD_ENTITY.getLocalPart())) return toEntity(value); if(local.equalsIgnoreCase(Constants.XSD_FLOAT.getLocalPart())) return new Float(Caster.toDoubleValue(value)); if(local.equalsIgnoreCase(Constants.XSD_HEXBIN.getLocalPart())) return Caster.toBinary(value); if(local.equalsIgnoreCase(Constants.XSD_ID.getLocalPart())) return Caster.toString(value); if(local.equalsIgnoreCase(Constants.XSD_IDREF.getLocalPart())) return Caster.toString(value); if(local.equalsIgnoreCase(Constants.XSD_IDREFS.getLocalPart())) return Caster.toString(value); if(local.equalsIgnoreCase(Constants.XSD_INT.getLocalPart())) return Caster.toInteger(value); if(local.equalsIgnoreCase(Constants.XSD_INTEGER.getLocalPart())) return Caster.toInteger(value); if(local.equalsIgnoreCase(Constants.XSD_LANGUAGE.getLocalPart())) return toLanguage(value); if(local.equalsIgnoreCase(Constants.XSD_LONG.getLocalPart())) return Caster.toLong(value); if(local.equalsIgnoreCase(Constants.XSD_MONTH.getLocalPart())) return toMonth(value); if(local.equalsIgnoreCase(Constants.XSD_MONTHDAY.getLocalPart())) return toMonthDay(value); if(local.equalsIgnoreCase(Constants.XSD_NAME.getLocalPart())) return toName(value); if(local.equalsIgnoreCase(Constants.XSD_NCNAME.getLocalPart())) return toNCName(value); if(local.equalsIgnoreCase(Constants.XSD_NEGATIVEINTEGER.getLocalPart())) return Caster.toInteger(value); if(local.equalsIgnoreCase(Constants.XSD_NMTOKEN.getLocalPart())) return toNMToken(value); if(local.equalsIgnoreCase(Constants.XSD_NMTOKENS.getLocalPart())) return toNMTokens(value); if(local.equalsIgnoreCase(Constants.XSD_NONNEGATIVEINTEGER.getLocalPart())) return Caster.toInteger(value); if(local.equalsIgnoreCase(Constants.XSD_NONPOSITIVEINTEGER.getLocalPart())) return Caster.toInteger(value); if(local.equalsIgnoreCase(Constants.XSD_NORMALIZEDSTRING.getLocalPart())) return Caster.toString(value); if(local.equalsIgnoreCase(Constants.XSD_POSITIVEINTEGER.getLocalPart())) return Caster.toInteger(value); if(local.equalsIgnoreCase(Constants.XSD_QNAME.getLocalPart())) return toQName(value); if(local.equalsIgnoreCase(Constants.XSD_SCHEMA.getLocalPart())) return toQName(value); if(local.equalsIgnoreCase(Constants.XSD_SHORT.getLocalPart())) return Caster.toShort(value); if(local.equalsIgnoreCase(Constants.XSD_TIME.getLocalPart())) return DateCaster.toTime(tz,value); if(local.equalsIgnoreCase(Constants.XSD_TIMEINSTANT1999.getLocalPart())) return DateCaster.toTime(tz,value); if(local.equalsIgnoreCase(Constants.XSD_TIMEINSTANT2000.getLocalPart())) return DateCaster.toTime(tz,value); if(local.equalsIgnoreCase(Constants.XSD_TOKEN.getLocalPart())) return toToken(value); if(local.equalsIgnoreCase(Constants.XSD_UNSIGNEDBYTE.getLocalPart())) return Caster.toByte(value); if(local.equalsIgnoreCase(Constants.XSD_UNSIGNEDINT.getLocalPart())) return Caster.toInteger(value); if(local.equalsIgnoreCase(Constants.XSD_UNSIGNEDLONG.getLocalPart())) return Caster.toLong(value); if(local.equalsIgnoreCase(Constants.XSD_UNSIGNEDSHORT.getLocalPart())) return Caster.toShort(value); if(local.equalsIgnoreCase(Constants.XSD_YEAR.getLocalPart())) return toYear(value); if(local.equalsIgnoreCase(Constants.XSD_YEARMONTH.getLocalPart())) return toYearMonth(value); return _toDefinedType(tm, null,null,null, value, done); } private static ArrayList<Object> toArrayList(TypeMapping tm,Object value, Set<Object> done) throws PageException { Array arr = Caster.toArray(value); ArrayList<Object> al=new ArrayList<Object>(); int len=arr.size(); Object o; for(int i=0;i<len;i++) { o=arr.get(i+1,null); al.add(i,_toAxisType(tm,null,null,null,null,o,done)); } return al; } private static Object[] toNativeArray(TypeMapping tm,Class targetClass,Object value, Set<Object> done) throws PageException { Object[] objs = Caster.toNativeArray(value); Object[] rtns; Class<?> componentClass = null; if(targetClass!=null) { componentClass = targetClass.getComponentType(); } if(componentClass!=null) { componentClass=toAxisTypeClass(componentClass); rtns = (Object[]) java.lang.reflect.Array.newInstance(componentClass, objs.length); } else rtns = new Object[objs.length]; try{ for(int i=0;i<objs.length;i++) { rtns[i]=_toAxisType(tm,null,null,null,componentClass,objs[i],done); } } // just in case something goes wrong with typed array catch(ArrayStoreException ase){ rtns = new Object[objs.length]; for(int i=0;i<objs.length;i++) { rtns[i]=_toAxisType(tm,null,null,null,componentClass,objs[i],done); } } return rtns; } private static Vector<Object> toVector(TypeMapping tm,Object value, Set<Object> done) throws PageException { Array arr = Caster.toArray(value); Vector<Object> v=new Vector<Object>(); int len=arr.size(); Object o; for(int i=0;i<len;i++) { o=arr.get(i+1,null); v.set(i,_toAxisType(tm,null,null,null,null,o,done)); } return v; } public static Component toComponent(PageContext pc, Pojo pojo, String compPath , Component defaultValue) { try { Component cfc = pc.loadComponent(compPath); Property[] props = cfc.getProperties(false, true, false, false); PojoIterator it=new PojoIterator(pojo); // only when the same amount of properties if(props.length==it.size()) { Map<Collection.Key, Property> propMap = toMap(props); Property p; Pair<Collection.Key,Object> pair; ComponentScope scope = cfc.getComponentScope(); while(it.hasNext()){ pair=it.next(); p=propMap.get(pair.getName()); if(p==null) return defaultValue; Object val = null; try { val = Caster.castTo(pc, p.getType(), pair.getValue(), false); } catch (PageException e) { } // store in variables and this scope scope.setEL(pair.getName(), val); cfc.setEL(pair.getName(), val); } return cfc; } } catch (PageException e) {} return defaultValue; } private static Map<Collection.Key,Property> toMap(Property[] props) { Map<Collection.Key,Property> map=new HashMap<Collection.Key, Property>(); for(int i=0;i<props.length;i++){ map.put(KeyImpl.init(props[i].getName()), props[i]); } return map; } public static Pojo toPojo(Pojo pojo, TypeMapping tm,TypeEntry typeEntry,QName type,Component comp, Set<Object> done) throws PageException { PageContext pc = ThreadLocalPageContext.get(); try { return _toPojo(pc,pojo, tm,typeEntry,type, comp,done); } catch (Exception e) { throw Caster.toPageException(e); } } private static Pojo _toPojo(PageContext pc, Pojo pojo, TypeMapping tm,TypeEntry typeEntry,QName type,Component comp, Set<Object> done) throws PageException {//print.ds();System.exit(0); comp=ComponentSpecificAccess.toComponentSpecificAccess(Component.ACCESS_PRIVATE,comp); ComponentScope scope = comp.getComponentScope(); // create Pojo if(pojo==null) { try { pojo = (Pojo) ClassUtil.loadInstance(ComponentUtil.getComponentPropertiesClass(pc,comp)); } catch (ClassException e) { throw Caster.toPageException(e); } } // initialize Pojo Property[] props=comp.getProperties(false, true, false, false); _initPojo(pc,typeEntry,type,pojo,props,scope,comp,tm,done); return pojo; } public static Pojo toPojo(Pojo pojo, TypeMapping tm,TypeEntry typeEntry,QName type,Struct sct, Set<Object> done) throws PageException { PageContext pc = ThreadLocalPageContext.get(); try { return _toPojo(pc,pojo, tm,typeEntry,type, sct,done); } catch (Exception e) { throw Caster.toPageException(e); } } private static Pojo _toPojo(PageContext pc, Pojo pojo, TypeMapping tm,TypeEntry typeEntry,QName type,Struct sct, Set<Object> done) throws PageException {//print.ds();System.exit(0); if(pojo==null) { try { PhysicalClassLoader cl=(PhysicalClassLoader) pc.getConfig().getRPCClassLoader(false); pojo = (Pojo) ClassUtil.loadInstance(ComponentUtil.getStructPropertiesClass(pc,sct,cl)); } catch (ClassException e) { throw Caster.toPageException(e); } catch (IOException e) { throw Caster.toPageException(e); } } // initialize List<Property> props=new ArrayList<Property>(); Iterator<Entry<Key, Object>> it = sct.entryIterator(); Entry<Key, Object> e; PropertyImpl p; while(it.hasNext()){ e = it.next(); p=new PropertyImpl(); p.setAccess(Component.ACCESS_PUBLIC); p.setName(e.getKey().getString()); p.setType(e.getValue()==null?"any":Caster.toTypeName(e.getValue())); props.add(p); } _initPojo(pc,typeEntry,type,pojo,props.toArray(new Property[props.size()]),sct,null,tm,done); return pojo; } private static void _initPojo(PageContext pc, TypeEntry typeEntry, QName type, Pojo pojo, Property[] props, Struct sct, Component comp, TypeMapping tm, Set<Object> done) throws PageException { Property p; Object v; Collection.Key k; CFMLExpressionInterpreter interpreter = new CFMLExpressionInterpreter(false); for(int i=0;i<props.length;i++){ p=props[i]; k=Caster.toKey(p.getName()); // value v=sct.get(k,null); if(v==null && comp!=null)v=comp.get(k, null); // default if(v!=null)v=Caster.castTo(pc, p.getType(), v, false); else{ if(!StringUtil.isEmpty(p.getDefault())){ try { v=Caster.castTo(pc, p.getType(), p.getDefault(), false); } catch(PageException pe) { try { v=interpreter.interpret(pc, p.getDefault()); v=Caster.castTo(pc, p.getType(), v, false); } catch(PageException pe2) { throw new ExpressionException("can not use default value ["+p.getDefault()+"] for property ["+p.getName()+"] with type ["+p.getType()+"]"); } } } } // set or throw if(v==null) { if(p.isRequired())throw new ExpressionException("required property ["+p.getName()+"] is not defined"); } else { TypeEntry childTE=null; QName childT=null; if(typeEntry!=null) { childTE = AxisUtil.getContainedElement(typeEntry,p.getName(),null); if(childTE!=null) childT=childTE.getQName(); } Reflector.callSetter(pojo, p.getName().toLowerCase(), _toAxisType(tm,null,childTE,childT,null,v,done)); } } } private static QueryBean toQueryBean(TypeMapping tm,Object value, Set<Object> done) throws PageException { Query query = Caster.toQuery(value); int recordcount=query.getRecordcount(); String[] columnList = query.getColumns(); QueryColumn[] columns=new QueryColumn[columnList.length]; Object[][] data = new Object[recordcount][columnList.length]; for(int i=0;i<columnList.length;i++) { columns[i]=query.getColumn(columnList[i]); } int row; for(row=1;row<=recordcount;row++) { for(int i=0;i<columns.length;i++) { data[row-1][i]=_toAxisType(tm,null,null,null,null,columns[i].get(row,null),done); } } QueryBean qb = new QueryBean(); qb.setColumnList(columnList); qb.setData(data); return qb; } private static Map<String,Object> toMap(TypeMapping tm,Object value, Set<Object> done) throws PageException { Struct src = Caster.toStruct(value); HashMap<String,Object> trg=new HashMap<String,Object>(); Iterator<Entry<Key, Object>> it = src.entryIterator(); Entry<Key, Object> e; while(it.hasNext()) { e = it.next(); trg.put(e.getKey().getString(),_toAxisType(tm,null,null,null,null,e.getValue(),done)); } return trg; } private static Object _toDefinedType(TypeMapping tm,TypeEntry typeEntry,QName type,Class targetClass,Object value,Set<Object> done) throws PageException { // Date if(value instanceof Date) {// not set to Decision.isDate(value) return new Date(((Date)value).getTime()); } Class clazz=type==null?null:((org.apache.axis.encoding.TypeMapping)tm).getClassForQName(type); // Pojo if(clazz!=null && Reflector.isInstaneOf(clazz,Pojo.class)) { Pojo pojo; try{ pojo=(Pojo) ClassUtil.loadInstance(clazz); } catch(Throwable t){ ExceptionUtil.rethrowIfNecessary(t); throw Caster.toPageException(t); } // Struct if(Decision.isStruct(value)) { if(value instanceof Component) return toPojo(pojo,tm,typeEntry,type,(Component)value,done); return toPojo(pojo,tm,typeEntry,type,Caster.toStruct(value),done); } } // No Mapping found // Array if(Decision.isArray(value) && !(value instanceof Argument)) { if(value instanceof byte[]) return value; return toNativeArray(tm,targetClass,value,done); } // Struct if(Decision.isStruct(value)) { if(value instanceof Component) { Object pojo= toPojo(null,tm,null,null,(Component)value,done); try { if(type==null || type.getLocalPart().equals("anyType")) { type= new QName(getRequestDefaultNameSpace(),pojo.getClass().getName()); //type= new QName(getRequestNameSpace(),pojo.getClass().getName()); //print.ds("missing type for "+pojo.getClass().getName()); } TypeMappingUtil.registerBeanTypeMapping(tm, pojo.getClass(), type); } catch(Throwable fault){ ExceptionUtil.rethrowIfNecessary(fault); throw Caster.toPageException(fault); } return pojo; } /*if(type!=null && !type.getLocalPart().equals("anyType")) { Object pojo= toPojo(null,tm,Caster.toStruct(value),targetClass,done); //Map<String, Object> map = toMap(tm,value,targetClass,done); //TypeMappingUtil.registerMapTypeMapping(tm, map.getClass(), type); TypeMappingUtil.registerBeanTypeMapping(tm, pojo.getClass(), type); return pojo; }*/ return toMap(tm,value,done); } // Query if(Decision.isQuery(value)) return toQueryBean(tm,value,done); // Other return value; } public static Class toAxisTypeClass(Class clazz) { if(clazz.isArray()) { return ClassUtil.toArrayClass(toAxisTypeClass(clazz.getComponentType())); } if(Query.class==clazz) return QueryBean.class; if(Array.class==clazz) return Object[].class; if(Struct.class==clazz) return Map.class; //if(Struct[].class==clazz) return Map[].class; //if(Query[].class==clazz) return QueryBean[].class; return clazz; } private static Object toURI(Object value) throws PageException { if(value instanceof URI) return value; if(value instanceof java.net.URI) return value; try { return new URI(Caster.toString(value)); } catch (MalformedURIException e) { throw Caster.toPageException(e); } } private static Token toToken(Object value) throws PageException { if(value instanceof Token) return (Token) value; return new Token(Caster.toString(value)); } private static QName toQName(Object value) throws PageException { if(value instanceof QName) return (QName) value; return new QName(Caster.toString(value)); } private static NMTokens toNMTokens(Object value) throws PageException { if(value instanceof NMTokens) return (NMTokens) value; return new NMTokens(Caster.toString(value)); } private static NMToken toNMToken(Object value) throws PageException { if(value instanceof NMToken) return (NMToken) value; return new NMToken(Caster.toString(value)); } private static NCName toNCName(Object value) throws PageException { if(value instanceof NCName) return (NCName) value; return new NCName(Caster.toString(value)); } private static Name toName(Object value) throws PageException { if(value instanceof Name) return (Name) value; return new Name(Caster.toString(value)); } private static Language toLanguage(Object value) throws PageException { if(value instanceof Language) return (Language) value; return new Language(Caster.toString(value)); } private static Entities toEntities(Object value) throws PageException { if(value instanceof Entities) return (Entities) value; return new Entities(Caster.toString(value)); } private static Entity toEntity(Object value) throws PageException { if(value instanceof Entity) return (Entity) value; return new Entity(Caster.toString(value)); } private static Day toDay(Object value) throws PageException { if(value instanceof Day) return (Day) value; if(Decision.isDateSimple(value,false)) { return new Day(Caster.toDate(value,null).getDate()); } try { return new Day(Caster.toIntValue(value)); } catch (Exception e) { try { return new Day(Caster.toString(value)); } catch (NumberFormatException nfe) { throw Caster.toPageException(nfe); } catch (ExpressionException ee) { throw ee; } } } private static Year toYear(Object value) throws PageException { if(value instanceof Year) return (Year) value; if(Decision.isDateSimple(value,false)) { return new Year(Caster.toDate(value,null).getYear()); } try { return new Year(Caster.toIntValue(value)); } catch (Exception e) { try { return new Year(Caster.toString(value)); } catch (NumberFormatException nfe) { throw Caster.toPageException(nfe); } catch (ExpressionException ee) { throw ee; } } } private static Month toMonth(Object value) throws PageException { if(value instanceof Month) return (Month) value; if(Decision.isDateSimple(value,false)) { return new Month(Caster.toDate(value,null).getMonth()); } try { return new Month(Caster.toIntValue(value)); } catch (Exception e) { try { return new Month(Caster.toString(value)); } catch (NumberFormatException nfe) { throw Caster.toPageException(nfe); } catch (ExpressionException ee) { throw ee; } } } private static YearMonth toYearMonth(Object value) throws PageException { if(value instanceof YearMonth) return (YearMonth) value; if(Decision.isDateSimple(value,false)) { DateTime dt = Caster.toDate(value,null); return new YearMonth(dt.getYear(),dt.getMonth()); } try { return new YearMonth(Caster.toString(value)); } catch (NumberFormatException nfe) { throw Caster.toPageException(nfe); } catch (ExpressionException ee) { throw ee; } } private static MonthDay toMonthDay(Object value) throws PageException { if(value instanceof MonthDay) return (MonthDay) value; if(Decision.isDateSimple(value,false)) { DateTime dt = Caster.toDate(value,null); return new MonthDay(dt.getMonth(),dt.getDate()); } try { return new MonthDay(Caster.toString(value)); } catch (NumberFormatException nfe) { throw Caster.toPageException(nfe); } catch (ExpressionException ee) { throw ee; } } private static Duration toDuration(Object value) throws PageException, IllegalArgumentException { if(value instanceof Duration) return (Duration) value; try { TimeSpan ts = Caster.toTimespan(value); return new Duration(true, 0, 0, ts.getDay(), ts.getHour(), ts.getMinute(), ts.getSecond()); } catch (PageException e) { return new Duration(Caster.toString(value)); } } public static Object toLuceeType(PageContext pc, Object value) throws PageException { return toLuceeType(pc, null, value); } public static Object toLuceeType(PageContext pc, String customType, Object value) throws PageException { pc=ThreadLocalPageContext.get(pc); if(pc!=null && value instanceof Pojo) { if(!StringUtil.isEmpty(customType)){ Component cfc = toComponent(pc, (Pojo)value,customType, null); if(cfc!=null) return cfc; } /* // try package/class name as component name String compPath=value.getClass().getName(); Component cfc = toComponent(pc, (Pojo)value, compPath, null); if(cfc!=null) return cfc; // try class name as component name compPath=ListUtil.last(compPath, '.'); cfc = toComponent(pc, (Pojo)value, compPath, null); if(cfc!=null) return cfc; */ } if(value instanceof Date || value instanceof Calendar) {// do not change to caster.isDate return Caster.toDate(value,null); } if(value instanceof Object[]) { Object[] arr=(Object[]) value; if(!ArrayUtil.isEmpty(arr)){ boolean allTheSame=true; // byte if(arr[0] instanceof Byte){ for(int i=1;i<arr.length;i++){ if(!(arr[i] instanceof Byte)){ allTheSame=false; break; } } if(allTheSame){ byte[] bytes=new byte[arr.length]; for(int i=0;i<arr.length;i++){ bytes[i]=Caster.toByteValue(arr[i]); } return bytes; } } } } if(value instanceof Byte[]) { Byte[] arr=(Byte[]) value; if(!ArrayUtil.isEmpty(arr)){ byte[] bytes=new byte[arr.length]; for(int i=0;i<arr.length;i++){ bytes[i]=arr[i].byteValue(); } return bytes; } } if(value instanceof byte[]) { return value; } if(Decision.isArray(value)) { Array a = Caster.toArray(value); int len=a.size(); Object o; String ct; for(int i=1;i<=len;i++) { o=a.get(i,null); if(o!=null) { ct=customType!=null && customType.endsWith("[]")?customType.substring(0,customType.length()-2):null; a.setEL(i,toLuceeType(pc,ct,o)); } } return a; } if(value instanceof Map) { Struct sct = new StructImpl(); Iterator it=((Map)value).entrySet().iterator(); Map.Entry entry; while(it.hasNext()) { entry=(Entry) it.next(); sct.setEL(Caster.toString(entry.getKey()),toLuceeType(pc,null,entry.getValue())); } return sct; //return StructUtil.copyToStruct((Map)value); } if(isQueryBean(value)) { QueryBean qb = (QueryBean) value; String[] strColumns = qb.getColumnList(); Object[][] data = qb.getData(); int recorcount=data.length; Query qry=new QueryImpl(strColumns,recorcount,"QueryBean"); QueryColumn[] columns=new QueryColumn[strColumns.length]; for(int i=0;i<columns.length;i++) { columns[i]=qry.getColumn(strColumns[i]); } int row; for(row=1;row<=recorcount;row++) { for(int i=0;i<columns.length;i++) { columns[i].set(row,toLuceeType(pc,null,data[row-1][i])); } } return qry; } if(Decision.isQuery(value)) { Query q = Caster.toQuery(value); int recorcount=q.getRecordcount(); String[] strColumns = q.getColumns(); QueryColumn col; int row; for(int i=0;i<strColumns.length;i++) { col=q.getColumn(strColumns[i]); for(row=1;row<=recorcount;row++) { col.set(row,toLuceeType(pc,null,col.get(row,null))); } } return q; } return value; } private static boolean isQueryBean(Object value) { return (value instanceof QueryBean); } public static QName toComponentType(QName qName, QName defaultValue) { String lp = qName.getLocalPart(); String uri = qName.getNamespaceURI(); if(lp.startsWith("ArrayOf")) return new QName(uri, lp.substring(7)); return defaultValue; } public static String getRequestNameSpace() { String rawURL = ReqRspUtil.getRequestURL(ThreadLocalPageContext.get().getHttpServletRequest(),false); String urlPath =""; try { urlPath = new java.net.URL(rawURL).getPath(); } catch (MalformedURLException e) {} String pathWithoutContext = urlPath.replaceFirst("/[^/]*", ""); return lucee.runtime.config.Constants.WEBSERVICE_NAMESPACE_URI + pathWithoutContext.toLowerCase(); } public static String getRequestDefaultNameSpace() { return lucee.runtime.config.Constants.WEBSERVICE_NAMESPACE_URI; } }