package railo.runtime.java; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import railo.runtime.PageContext; import railo.runtime.dump.DumpData; import railo.runtime.dump.DumpProperties; import railo.runtime.dump.DumpUtil; import railo.runtime.exp.ExpressionException; import railo.runtime.exp.PageException; import railo.runtime.op.Caster; import railo.runtime.op.Operator; import railo.runtime.op.date.DateCaster; import railo.runtime.reflection.Reflector; import railo.runtime.reflection.pairs.MethodInstance; import railo.runtime.type.Collection; import railo.runtime.type.ObjectWrap; import railo.runtime.type.Objects; import railo.runtime.type.Struct; import railo.runtime.type.dt.DateTime; import railo.runtime.type.util.ArrayUtil; import railo.runtime.util.VariableUtil; import railo.runtime.util.VariableUtilImpl; /** * class to handle initialising and call native object from railo */ public class JavaObject implements Objects,ObjectWrap { private Class clazz; private boolean isInit=false; private Object object; private VariableUtil variableUtil; /** * constructor with className to load * @param variableUtil * @param clazz * @throws ExpressionException */ public JavaObject(VariableUtil variableUtil,Class clazz) { this.variableUtil=variableUtil; this.clazz=clazz; } public JavaObject(VariableUtil variableUtil,Object object) { this.variableUtil=variableUtil; this.clazz=object.getClass(); this.object=object; isInit=true; } public Object get(PageContext pc, String propertyName) throws PageException { if(isInit) { return variableUtil.get(pc,object,propertyName); } // Check Field Field[] fields = Reflector.getFieldsIgnoreCase(clazz,propertyName,null); if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) { try { return fields[0].get(null); } catch (Exception e) { throw Caster.toPageException(e); } } // Getter MethodInstance mi = Reflector.getGetterEL(clazz,propertyName); if(mi!=null) { if(Modifier.isStatic(mi.getMethod().getModifiers())) { try { return mi.invoke(null); } catch (IllegalAccessException e) { throw Caster.toPageException(e); } catch (InvocationTargetException e) { throw Caster.toPageException(e.getTargetException()); } } } // male Instance return variableUtil.get(pc,init(),propertyName); } @Override public Object get(PageContext pc, Collection.Key key) throws PageException { return get(pc, key.getString()); } public Object get(PageContext pc, String propertyName, Object defaultValue) { if(isInit) { return variableUtil.get(pc,object,propertyName,defaultValue); } // Field Field[] fields = Reflector.getFieldsIgnoreCase(clazz,propertyName,null); if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) { try { return fields[0].get(null); } catch (Exception e) {} } // Getter MethodInstance mi = Reflector.getGetterEL(clazz,propertyName); if(mi!=null) { if(Modifier.isStatic(mi.getMethod().getModifiers())) { try { return mi.invoke(null); } catch (Exception e) {} } } try { return variableUtil.get(pc,init(),propertyName,defaultValue); } catch (PageException e1) { return defaultValue; } } @Override public Object get(PageContext pc, Collection.Key key, Object defaultValue) { return get(pc, key.getString(), defaultValue); } @Override public Object set(PageContext pc, Collection.Key propertyName, Object value) throws PageException { if(isInit) { return ((VariableUtilImpl)variableUtil).set(pc,object,propertyName,value); } // Field Field[] fields=Reflector.getFieldsIgnoreCase(clazz,propertyName.getString(),null); if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) { try { fields[0].set(null,value); return value; } catch (Exception e) { Caster.toPageException(e); } } // Getter MethodInstance mi = Reflector.getSetter(clazz,propertyName.getString(),value,null); if(mi!=null) { if(Modifier.isStatic(mi.getMethod().getModifiers())) { try { return mi.invoke(null); } catch (IllegalAccessException e) { throw Caster.toPageException(e); } catch (InvocationTargetException e) { throw Caster.toPageException(e.getTargetException()); } } } return ((VariableUtilImpl)variableUtil).set(pc,init(),propertyName,value); } @Override public Object setEL(PageContext pc, Collection.Key propertyName, Object value) { if(isInit) { return variableUtil.setEL(pc,object,propertyName,value); } // Field Field[] fields=Reflector.getFieldsIgnoreCase(clazz,propertyName.getString(),null); if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) { try { fields[0].set(null,value); } catch (Exception e) {} return value; } // Getter MethodInstance mi = Reflector.getSetter(clazz,propertyName.getString(),value,null); if(mi!=null) { if(Modifier.isStatic(mi.getMethod().getModifiers())) { try { return mi.invoke(null); } catch (Exception e) {} } } try { return variableUtil.setEL(pc,init(),propertyName,value); } catch (PageException e1) { return value; } } public Object call(PageContext pc, String methodName, Object[] arguments) throws PageException { if(arguments==null)arguments=new Object[0]; // init if(methodName.equalsIgnoreCase("init")) { return init(arguments); } else if(isInit) { return Reflector.callMethod(object,methodName,arguments); } try { // get method MethodInstance mi = Reflector.getMethodInstance(this,clazz,methodName,arguments); // call static method if exist if(Modifier.isStatic(mi.getMethod().getModifiers())) { return mi.invoke(null); } if(arguments.length==0 && methodName.equalsIgnoreCase("getClass")){ return clazz; } // invoke constructor and call instance method return mi.invoke(init()); } catch(InvocationTargetException e) { Throwable target = e.getTargetException(); if(target instanceof PageException) throw (PageException)target; throw Caster.toPageException(e.getTargetException()); } catch(Exception e) { throw Caster.toPageException(e); } } @Override public Object call(PageContext pc, Collection.Key methodName, Object[] arguments) throws PageException { return call(pc, methodName.getString(), arguments); } public Object callWithNamedValues(PageContext pc, String methodName, Struct args) throws PageException { Iterator<Object> it = args.valueIterator(); List<Object> values=new ArrayList<Object>(); while(it.hasNext()) { values.add(it.next()); } return call(pc,methodName,values.toArray(new Object[values.size()])); } public Object callWithNamedValues(PageContext pc, Collection.Key methodName, Struct args) throws PageException { return callWithNamedValues(pc, methodName.getString(), args); } /** * initialize method (default no object) * @return initialize object * @throws PageException */ private Object init() throws PageException { return init(new Object[0]); } private Object init(Object defaultValue) { return init(new Object[0],defaultValue); } /** * initialize method * @param arguments * @return Initalised Object * @throws PageException */ private Object init(Object[] arguments) throws PageException { object=Reflector.callConstructor(clazz,arguments); isInit=true; return object; } private Object init(Object[] arguments, Object defaultValue) { object=Reflector.callConstructor(clazz,arguments,defaultValue); isInit=object!=defaultValue; return object; } @Override public Object getEmbededObject() throws PageException { if(object==null)init(); return object; } @Override public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties props) { try { return DumpUtil.toDumpData(getEmbededObject(), pageContext,maxlevel,props); } catch (PageException e) { return DumpUtil.toDumpData(clazz, pageContext,maxlevel,props); } } /** * @return the containing Class */ public Class getClazz() {return clazz;} public boolean isInitalized() { return isInit; } @Override public String castToString() throws PageException { return Caster.toString(getEmbededObject()); } @Override public String castToString(String defaultValue) { try { return Caster.toString(getEmbededObject(),defaultValue); } catch (PageException e) { return defaultValue; } } @Override public boolean castToBooleanValue() throws PageException { return Caster.toBooleanValue(getEmbededObject()); } @Override public Boolean castToBoolean(Boolean defaultValue) { try { return Caster.toBoolean(getEmbededObject(),defaultValue); } catch (PageException e) { return defaultValue; } } @Override public double castToDoubleValue() throws PageException { return Caster.toDoubleValue(getEmbededObject()); } @Override public double castToDoubleValue(double defaultValue) { try { return Caster.toDoubleValue(getEmbededObject(),defaultValue); } catch (PageException e) { return defaultValue; } } @Override public DateTime castToDateTime() throws PageException { return Caster.toDatetime(getEmbededObject(),null); } @Override public DateTime castToDateTime(DateTime defaultValue) { try { return DateCaster.toDateAdvanced(getEmbededObject(),true,null,defaultValue); } catch (PageException e) { return defaultValue; } } @Override public Object getEmbededObject(Object def) { if(object==null)init(def); return object; } /** * @return the object */ public Object getObject() { return object; } @Override public int compareTo(boolean b) throws PageException { return Operator.compare(castToBooleanValue(), b); } @Override public int compareTo(DateTime dt) throws PageException { return Operator.compare((Date)castToDateTime(), (Date)dt); } @Override public int compareTo(double d) throws PageException { return Operator.compare(castToDoubleValue(), d); } @Override public int compareTo(String str) throws PageException { return Operator.compare(castToString(), str); } }