001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.java; 020 021import java.lang.reflect.Field; 022import java.lang.reflect.InvocationTargetException; 023import java.lang.reflect.Modifier; 024import java.util.ArrayList; 025import java.util.Date; 026import java.util.Iterator; 027import java.util.List; 028 029import lucee.runtime.PageContext; 030import lucee.runtime.dump.DumpData; 031import lucee.runtime.dump.DumpProperties; 032import lucee.runtime.dump.DumpUtil; 033import lucee.runtime.exp.ExpressionException; 034import lucee.runtime.exp.PageException; 035import lucee.runtime.op.Caster; 036import lucee.runtime.op.Operator; 037import lucee.runtime.op.date.DateCaster; 038import lucee.runtime.reflection.Reflector; 039import lucee.runtime.reflection.pairs.MethodInstance; 040import lucee.runtime.type.Collection; 041import lucee.runtime.type.ObjectWrap; 042import lucee.runtime.type.Objects; 043import lucee.runtime.type.Struct; 044import lucee.runtime.type.dt.DateTime; 045import lucee.runtime.type.util.ArrayUtil; 046import lucee.runtime.util.VariableUtil; 047import lucee.runtime.util.VariableUtilImpl; 048 049 050/** 051 * class to handle initialising and call native object from lucee 052 */ 053public class JavaObject implements Objects,ObjectWrap { 054 055 private Class clazz; 056 private boolean isInit=false; 057 private Object object; 058 private VariableUtil variableUtil; 059 060 /** 061 * constructor with className to load 062 * @param variableUtil 063 * @param clazz 064 * @throws ExpressionException 065 */ 066 public JavaObject(VariableUtil variableUtil,Class clazz) { 067 this.variableUtil=variableUtil; 068 this.clazz=clazz; 069 } 070 071 072 public JavaObject(VariableUtil variableUtil,Object object) { 073 this.variableUtil=variableUtil; 074 this.clazz=object.getClass(); 075 this.object=object; 076 isInit=true; 077 } 078 079 public Object get(PageContext pc, String propertyName) throws PageException { 080 if(isInit) { 081 return variableUtil.get(pc,object,propertyName); 082 } 083 084 // Check Field 085 Field[] fields = Reflector.getFieldsIgnoreCase(clazz,propertyName,null); 086 if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) { 087 try { 088 return fields[0].get(null); 089 } 090 catch (Exception e) { 091 throw Caster.toPageException(e); 092 } 093 } 094 // Getter 095 MethodInstance mi = Reflector.getGetterEL(clazz,propertyName); 096 if(mi!=null) { 097 if(Modifier.isStatic(mi.getMethod().getModifiers())) { 098 try { 099 return mi.invoke(null); 100 } 101 catch (IllegalAccessException e) { 102 throw Caster.toPageException(e); 103 } 104 catch (InvocationTargetException e) { 105 throw Caster.toPageException(e.getTargetException()); 106 } 107 } 108 } 109 // male Instance 110 return variableUtil.get(pc,init(),propertyName); 111 } 112 113 @Override 114 public Object get(PageContext pc, Collection.Key key) throws PageException { 115 return get(pc, key.getString()); 116 } 117 118 public Object get(PageContext pc, String propertyName, Object defaultValue) { 119 if(isInit) { 120 return variableUtil.get(pc,object,propertyName,defaultValue); 121 } 122 // Field 123 Field[] fields = Reflector.getFieldsIgnoreCase(clazz,propertyName,null); 124 if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) { 125 try { 126 return fields[0].get(null); 127 } catch (Exception e) {} 128 } 129 // Getter 130 MethodInstance mi = Reflector.getGetterEL(clazz,propertyName); 131 if(mi!=null) { 132 if(Modifier.isStatic(mi.getMethod().getModifiers())) { 133 try { 134 return mi.invoke(null); 135 } 136 catch (Exception e) {} 137 } 138 } 139 try { 140 return variableUtil.get(pc,init(),propertyName,defaultValue); 141 } catch (PageException e1) { 142 return defaultValue; 143 } 144 } 145 146 @Override 147 public Object get(PageContext pc, Collection.Key key, Object defaultValue) { 148 return get(pc, key.getString(), defaultValue); 149 } 150 151 @Override 152 public Object set(PageContext pc, Collection.Key propertyName, Object value) throws PageException { 153 if(isInit) { 154 return ((VariableUtilImpl)variableUtil).set(pc,object,propertyName,value); 155 } 156 // Field 157 Field[] fields=Reflector.getFieldsIgnoreCase(clazz,propertyName.getString(),null); 158 if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) { 159 try { 160 fields[0].set(null,value); 161 return value; 162 } catch (Exception e) { 163 Caster.toPageException(e); 164 } 165 } 166 // Getter 167 MethodInstance mi = Reflector.getSetter(clazz,propertyName.getString(),value,null); 168 if(mi!=null) { 169 if(Modifier.isStatic(mi.getMethod().getModifiers())) { 170 try { 171 return mi.invoke(null); 172 } 173 catch (IllegalAccessException e) { 174 throw Caster.toPageException(e); 175 } 176 catch (InvocationTargetException e) { 177 throw Caster.toPageException(e.getTargetException()); 178 } 179 } 180 } 181 182 183 return ((VariableUtilImpl)variableUtil).set(pc,init(),propertyName,value); 184 } 185 186 @Override 187 public Object setEL(PageContext pc, Collection.Key propertyName, Object value) { 188 if(isInit) { 189 return variableUtil.setEL(pc,object,propertyName,value); 190 } 191 // Field 192 Field[] fields=Reflector.getFieldsIgnoreCase(clazz,propertyName.getString(),null); 193 if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) { 194 try { 195 fields[0].set(null,value); 196 } catch (Exception e) {} 197 return value; 198 } 199 // Getter 200 MethodInstance mi = Reflector.getSetter(clazz,propertyName.getString(),value,null); 201 if(mi!=null) { 202 if(Modifier.isStatic(mi.getMethod().getModifiers())) { 203 try { 204 return mi.invoke(null); 205 } 206 catch (Exception e) {} 207 } 208 } 209 210 try { 211 return variableUtil.setEL(pc,init(),propertyName,value); 212 } catch (PageException e1) { 213 return value; 214 } 215 } 216 217 public Object call(PageContext pc, String methodName, Object[] arguments) throws PageException { 218 if(arguments==null)arguments=new Object[0]; 219 220 // edge cases 221 if(methodName.equalsIgnoreCase("init")) { 222 return init(arguments); 223 } 224 else if(methodName.equalsIgnoreCase("getClass")) { 225 return clazz; 226 } 227 else if(isInit) { 228 return Reflector.callMethod(object,methodName,arguments); 229 } 230 231 232 try { 233 // get method 234 MethodInstance mi = Reflector.getMethodInstance(this,clazz,methodName,arguments); 235 // call static method if exist 236 if(Modifier.isStatic(mi.getMethod().getModifiers())) { 237 return mi.invoke(null); 238 } 239 240 if(arguments.length==0 && methodName.equalsIgnoreCase("getClass")){ 241 return clazz; 242 } 243 244 // invoke constructor and call instance method 245 return mi.invoke(init()); 246 } 247 catch(InvocationTargetException e) { 248 Throwable target = e.getTargetException(); 249 if(target instanceof PageException) throw (PageException)target; 250 throw Caster.toPageException(e.getTargetException()); 251 } 252 catch(Exception e) { 253 throw Caster.toPageException(e); 254 } 255 } 256 257 @Override 258 public Object call(PageContext pc, Collection.Key methodName, Object[] arguments) throws PageException { 259 return call(pc, methodName.getString(), arguments); 260 } 261 262 public Object callWithNamedValues(PageContext pc, String methodName, Struct args) throws PageException { 263 Iterator<Object> it = args.valueIterator(); 264 List<Object> values=new ArrayList<Object>(); 265 while(it.hasNext()) { 266 values.add(it.next()); 267 } 268 return call(pc,methodName,values.toArray(new Object[values.size()])); 269 } 270 271 public Object callWithNamedValues(PageContext pc, Collection.Key methodName, Struct args) throws PageException { 272 return callWithNamedValues(pc, methodName.getString(), args); 273 } 274 275 /** 276 * initialize method (default no object) 277 * @return initialize object 278 * @throws PageException 279 */ 280 private Object init() throws PageException { 281 return init(new Object[0]); 282 } 283 284 private Object init(Object defaultValue) { 285 return init(new Object[0],defaultValue); 286 } 287 288 /** 289 * initialize method 290 * @param arguments 291 * @return Initalised Object 292 * @throws PageException 293 */ 294 private Object init(Object[] arguments) throws PageException { 295 object=Reflector.callConstructor(clazz,arguments); 296 isInit=true; 297 return object; 298 } 299 private Object init(Object[] arguments, Object defaultValue) { 300 object=Reflector.callConstructor(clazz,arguments,defaultValue); 301 isInit=object!=defaultValue; 302 return object; 303 } 304 305 306 @Override 307 public Object getEmbededObject() throws PageException { 308 if(object==null)init(); 309 return object; 310 } 311 312 @Override 313 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties props) { 314 try { 315 return DumpUtil.toDumpData(getEmbededObject(), pageContext,maxlevel,props); 316 } catch (PageException e) { 317 return DumpUtil.toDumpData(clazz, pageContext,maxlevel,props); 318 } 319 } 320 321 /** 322 * @return the containing Class 323 */ 324 public Class getClazz() {return clazz;} 325 326 public boolean isInitalized() { 327 return isInit; 328 } 329 330 @Override 331 public String castToString() throws PageException { 332 return Caster.toString(getEmbededObject()); 333 } 334 335 336 337 @Override 338 public String castToString(String defaultValue) { 339 try { 340 return Caster.toString(getEmbededObject(),defaultValue); 341 } catch (PageException e) { 342 return defaultValue; 343 } 344 } 345 346 347 @Override 348 public boolean castToBooleanValue() throws PageException { 349 return Caster.toBooleanValue(getEmbededObject()); 350 } 351 352 @Override 353 public Boolean castToBoolean(Boolean defaultValue) { 354 try { 355 return Caster.toBoolean(getEmbededObject(),defaultValue); 356 } catch (PageException e) { 357 return defaultValue; 358 } 359 } 360 361 @Override 362 public double castToDoubleValue() throws PageException { 363 return Caster.toDoubleValue(getEmbededObject()); 364 } 365 366 @Override 367 public double castToDoubleValue(double defaultValue) { 368 try { 369 return Caster.toDoubleValue(getEmbededObject(),true,defaultValue); 370 } catch (PageException e) { 371 return defaultValue; 372 } 373 } 374 375 @Override 376 public DateTime castToDateTime() throws PageException { 377 return Caster.toDatetime(getEmbededObject(),null); 378 } 379 380 @Override 381 public DateTime castToDateTime(DateTime defaultValue) { 382 try { 383 return DateCaster.toDateAdvanced(getEmbededObject(),DateCaster.CONVERTING_TYPE_OFFSET,null,defaultValue); 384 } catch (PageException e) { 385 return defaultValue; 386 } 387 } 388 389 @Override 390 public Object getEmbededObject(Object def) { 391 if(object==null)init(def); 392 return object; 393 } 394 395 /** 396 * @return the object 397 */ 398 public Object getObject() { 399 return object; 400 } 401 402 @Override 403 public int compareTo(boolean b) throws PageException { 404 return Operator.compare(castToBooleanValue(), b); 405 } 406 407 @Override 408 public int compareTo(DateTime dt) throws PageException { 409 return Operator.compare((Date)castToDateTime(), (Date)dt); 410 } 411 412 @Override 413 public int compareTo(double d) throws PageException { 414 return Operator.compare(castToDoubleValue(), d); 415 } 416 417 @Override 418 public int compareTo(String str) throws PageException { 419 return Operator.compare(castToString(), str); 420 } 421 422}