001 package railo.runtime.exp; 002 003 import java.lang.reflect.Method; 004 import java.util.ArrayList; 005 import java.util.Iterator; 006 import java.util.List; 007 import java.util.Set; 008 009 import railo.commons.lang.StringUtil; 010 import railo.runtime.PageContext; 011 import railo.runtime.PageContextImpl; 012 import railo.runtime.dump.DumpData; 013 import railo.runtime.dump.DumpProperties; 014 import railo.runtime.engine.ThreadLocalPageContext; 015 import railo.runtime.op.Castable; 016 import railo.runtime.op.Caster; 017 import railo.runtime.op.Decision; 018 import railo.runtime.reflection.Reflector; 019 import railo.runtime.reflection.pairs.MethodInstance; 020 import railo.runtime.type.Collection; 021 import railo.runtime.type.KeyImpl; 022 import railo.runtime.type.Objects; 023 import railo.runtime.type.Struct; 024 import railo.runtime.type.StructImpl; 025 import railo.runtime.type.it.EntryIterator; 026 import railo.runtime.type.it.KeyIterator; 027 import railo.runtime.type.it.StringIterator; 028 import railo.runtime.type.it.ValueIterator; 029 import railo.runtime.type.util.ArrayUtil; 030 import railo.runtime.type.util.KeyConstants; 031 import railo.runtime.type.util.StructUtil; 032 033 public class CatchBlockImpl extends StructImpl implements CatchBlock,Castable,Objects{ 034 035 private static final long serialVersionUID = -3680961614605720352L; 036 037 public static final Key MESSAGE = KeyConstants._Message; 038 public static final Key DETAIL = KeyConstants._Detail; 039 public static final Key ERROR_CODE = KeyImpl.intern("ErrorCode"); 040 public static final Key EXTENDEDINFO = KeyImpl.intern("ExtendedInfo"); 041 public static final Key EXTENDED_INFO = KeyImpl.intern("Extended_Info"); 042 public static final Key TAG_CONTEXT = KeyImpl.intern("TagContext"); 043 public static final Key STACK_TRACE = KeyImpl.intern("StackTrace"); 044 public static final Key ADDITIONAL = KeyImpl.intern("additional"); 045 private static final Object NULL = new Object(); 046 047 private PageExceptionImpl exception; 048 049 050 public CatchBlockImpl(PageExceptionImpl pe) { 051 this.exception=pe; 052 053 setEL(MESSAGE, new SpecialItem(pe, MESSAGE)); 054 setEL(DETAIL, new SpecialItem(pe, DETAIL)); 055 setEL(ERROR_CODE, new SpecialItem(pe, ERROR_CODE)); 056 setEL(EXTENDEDINFO, new SpecialItem(pe, EXTENDEDINFO)); 057 setEL(EXTENDED_INFO, new SpecialItem(pe, EXTENDED_INFO)); 058 setEL(ADDITIONAL, new SpecialItem(pe, ADDITIONAL)); 059 setEL(TAG_CONTEXT, new SpecialItem(pe, TAG_CONTEXT)); 060 setEL(KeyConstants._type, new SpecialItem(pe, KeyConstants._type)); 061 setEL(STACK_TRACE, new SpecialItem(pe, STACK_TRACE)); 062 063 064 if(pe instanceof NativeException){ 065 Throwable throwable = ((NativeException)pe).getRootCause(); 066 Method[] mGetters = Reflector.getGetters(throwable.getClass()); 067 Method getter; 068 Collection.Key key; 069 if(!ArrayUtil.isEmpty(mGetters)){ 070 for(int i=0;i<mGetters.length;i++){ 071 getter=mGetters[i]; 072 if(getter.getDeclaringClass()==Throwable.class) { 073 continue; 074 } 075 key=KeyImpl.init(Reflector.removeGetterPrefix(getter.getName())); 076 if(STACK_TRACE.equalsIgnoreCase(key)) continue; 077 setEL(key,new Pair(throwable,key, getter,false)); 078 } 079 } 080 } 081 } 082 083 084 class SpecialItem { 085 private PageExceptionImpl pe; 086 private Key key; 087 088 public SpecialItem(PageExceptionImpl pe, Key key) { 089 this.pe=pe; 090 this.key=key; 091 } 092 093 public Object get() { 094 if(key==MESSAGE) return StringUtil.emptyIfNull(pe.getMessage()); 095 if(key==DETAIL) return StringUtil.emptyIfNull(pe.getDetail()); 096 if(key==ERROR_CODE) return StringUtil.emptyIfNull(pe.getErrorCode()); 097 if(key==EXTENDEDINFO) return StringUtil.emptyIfNull(pe.getExtendedInfo()); 098 if(key==EXTENDED_INFO) return StringUtil.emptyIfNull(pe.getExtendedInfo()); 099 if(key==KeyConstants._type) return StringUtil.emptyIfNull(pe.getTypeAsString()); 100 if(key==STACK_TRACE) return StringUtil.emptyIfNull(pe.getStackTraceAsString()); 101 if(key==ADDITIONAL) return pe.getAddional(); 102 if(key==TAG_CONTEXT) return pe.getTagContext(ThreadLocalPageContext.getConfig()); 103 return null; 104 } 105 106 public void set(Object o){ 107 try { 108 if(!(o instanceof Pair)) { 109 if(key==DETAIL) { 110 pe.setDetail(Caster.toString(o)); 111 return; 112 } 113 else if(key==ERROR_CODE) { 114 pe.setErrorCode(Caster.toString(o)); 115 return; 116 } 117 else if(key==EXTENDEDINFO || key==EXTENDED_INFO) { 118 pe.setExtendedInfo(Caster.toString(o)); 119 return; 120 } 121 else if(key==STACK_TRACE) { 122 if(o instanceof StackTraceElement[]){ 123 pe.setStackTrace((StackTraceElement[])o); 124 return; 125 } 126 else if(Decision.isCastableToArray(o)) { 127 Object[] arr = Caster.toNativeArray(o); 128 StackTraceElement[] elements=new StackTraceElement[arr.length]; 129 for(int i=0;i<arr.length;i++) { 130 if(arr[i] instanceof StackTraceElement) 131 elements[i]=(StackTraceElement) arr[i]; 132 else 133 throw new CasterException(o, StackTraceElement[].class); 134 } 135 pe.setStackTrace(elements); 136 return; 137 138 } 139 } 140 } 141 } 142 catch(PageException pe){} 143 144 superSetEL(key,o); 145 146 147 } 148 public Object remove(){ 149 Object rtn=null; 150 if(key==DETAIL) { 151 rtn=pe.getDetail(); 152 pe.setDetail(""); 153 } 154 else if(key==ERROR_CODE) { 155 rtn=pe.getErrorCode(); 156 pe.setErrorCode("0"); 157 } 158 else if(key==EXTENDEDINFO || key==EXTENDED_INFO) { 159 rtn=pe.getExtendedInfo(); 160 pe.setExtendedInfo(null); 161 } 162 return rtn; 163 164 } 165 } 166 167 168 /** 169 * @return the pe 170 */ 171 public PageException getPageException() { 172 return exception; 173 } 174 175 @Override 176 public String castToString() throws ExpressionException { 177 return castToString(null); 178 } 179 180 @Override 181 public String castToString(String defaultValue) { 182 return exception.getClass().getName(); 183 } 184 185 @Override 186 public boolean containsValue(Object value) { 187 Key[] keys = keys(); 188 for(int i=0;i<keys.length;i++){ 189 if(get(keys[i],null)==value) return true; 190 } 191 return false; 192 } 193 194 @Override 195 public Collection duplicate(boolean deepCopy) { 196 Struct sct=new StructImpl(); 197 StructUtil.copy(this, sct, true); 198 return sct; 199 } 200 201 @Override 202 public Set entrySet() { 203 return StructUtil.entrySet(this); 204 } 205 206 public void print(PageContext pc){ 207 ((PageContextImpl)pc).handlePageException(exception); 208 209 } 210 211 @Override 212 public Object get(Key key, Object defaultValue) { 213 Object value = super.get(key,defaultValue); 214 if(value instanceof SpecialItem) { 215 return ((SpecialItem)value).get(); 216 } 217 else if(value instanceof Pair) { 218 Pair pair=(Pair) value; 219 try { 220 Object res = pair.getter.invoke(pair.throwable, new Object[]{}); 221 if(pair.doEmptyStringWhenNull && res==null) return ""; 222 return res; 223 } 224 catch (Exception e) { 225 return defaultValue; 226 } 227 } 228 return value; 229 } 230 231 @Override 232 public Object set(Key key, Object value) throws PageException { 233 Object curr = super.get(key,null); 234 if(curr instanceof SpecialItem){ 235 ((SpecialItem)curr).set(value); 236 return value; 237 } 238 else if(curr instanceof Pair){ 239 Pair pair=(Pair) curr; 240 MethodInstance setter = Reflector.getSetter(pair.throwable, pair.name.getString(), value,null); 241 if(setter!=null){ 242 try { 243 setter.invoke(pair.throwable); 244 return value; 245 } catch (Exception e) { 246 throw Caster.toPageException(e); 247 } 248 } 249 } 250 251 return super.set(key, value); 252 } 253 254 @Override 255 public Object setEL(Key key, Object value) { 256 Object curr = super.get(key,null); 257 if(curr instanceof SpecialItem){ 258 ((SpecialItem)curr).set(value); 259 return value; 260 } 261 else if(curr instanceof Pair){ 262 Pair pair=(Pair) curr; 263 MethodInstance setter = Reflector.getSetter(pair.throwable, pair.name.getString(), value,null); 264 if(setter!=null){ 265 try { 266 setter.invoke(pair.throwable); 267 } catch (Exception e) {} 268 return value; 269 } 270 } 271 return super.setEL(key, value); 272 } 273 274 private Object superSetEL(Key key, Object value) { 275 return super.setEL(key, value); 276 } 277 278 @Override 279 public int size() { 280 return keys().length; 281 } 282 283 @Override 284 public Key[] keys() { 285 Key[] keys = super.keys(); 286 List<Key> list=new ArrayList<Key>(); 287 for(int i=0;i<keys.length;i++){ 288 if(get(keys[i], null)!=null)list.add(keys[i]); 289 } 290 return list.toArray(new Key[list.size()]); 291 } 292 293 @Override 294 public Object remove(Key key) throws PageException { 295 Object curr = super.get(key,null); 296 if(curr instanceof SpecialItem){ 297 return ((SpecialItem)curr).remove(); 298 } 299 else if(curr instanceof Pair){ 300 Pair pair=(Pair) curr; 301 MethodInstance setter = Reflector.getSetter(pair.throwable, pair.name.getString(), null,null); 302 if(setter!=null){ 303 try { 304 Object before = pair.getter.invoke(pair.throwable, new Object[0]); 305 setter.invoke(pair.throwable); 306 return before; 307 } catch (Exception e) { 308 throw Caster.toPageException(e); 309 } 310 } 311 } 312 return super.remove(key); 313 } 314 315 @Override 316 public Iterator<Collection.Key> keyIterator() { 317 return new KeyIterator(keys()); 318 } 319 320 @Override 321 public Iterator<String> keysAsStringIterator() { 322 return new StringIterator(keys()); 323 } 324 325 @Override 326 public Iterator<Entry<Key, Object>> entryIterator() { 327 return new EntryIterator(this, keys()); 328 } 329 330 @Override 331 public Iterator<Object> valueIterator() { 332 return new ValueIterator(this, keys()); 333 } 334 335 @Override 336 public java.util.Collection values() { 337 return StructUtil.values(this); 338 } 339 340 @Override 341 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 342 return StructUtil.toDumpTable(this,"Catch",pageContext,maxlevel,dp); 343 } 344 345 346 347 class Pair{ 348 Throwable throwable; 349 Collection.Key name; 350 Method getter; 351 private boolean doEmptyStringWhenNull; 352 353 public Pair(Throwable throwable,Key name, Method method,boolean doEmptyStringWhenNull) { 354 this.throwable = throwable; 355 this.name = name; 356 this.getter = method; 357 this.doEmptyStringWhenNull = doEmptyStringWhenNull; 358 } 359 public Pair(Throwable throwable,String name, Method method, boolean doEmptyStringWhenNull) { 360 this(throwable, KeyImpl.init(name), method,doEmptyStringWhenNull); 361 } 362 363 public String toString(){ 364 try { 365 return Caster.toString(getter.invoke(throwable, new Object[]{})); 366 } catch (Exception e) { 367 throw new PageRuntimeException(Caster.toPageException(e)); 368 } 369 } 370 } 371 372 public Object call(PageContext pc, String methodName, Object[] arguments) throws PageException { 373 Object obj=exception; 374 if(exception instanceof NativeException) obj=((NativeException)exception).getRootCause(); 375 if("dump".equalsIgnoreCase(methodName)){ 376 print(pc); 377 return null; 378 } 379 380 try{ 381 return Reflector.callMethod(obj, methodName, arguments); 382 } 383 catch(PageException e){ 384 return Reflector.callMethod(exception, methodName, arguments); 385 } 386 } 387 388 389 390 391 public Object callWithNamedValues(PageContext pc, String methodName,Struct args) throws PageException { 392 throw new ApplicationException("named arguments not supported"); 393 } 394 395 public Object callWithNamedValues(PageContext pc, Key methodName,Struct args) throws PageException { 396 throw new ApplicationException("named arguments not supported"); 397 } 398 public boolean isInitalized() { 399 return true; 400 } 401 402 public Object set(PageContext pc, String propertyName, Object value) throws PageException { 403 return set(propertyName, value); 404 } 405 406 public Object set(PageContext pc, Key propertyName, Object value)throws PageException { 407 return set(propertyName, value); 408 } 409 410 public Object setEL(PageContext pc, String propertyName, Object value) { 411 return setEL(propertyName, value); 412 } 413 414 public Object setEL(PageContext pc, Key propertyName, Object value) { 415 return setEL(propertyName, value); 416 } 417 public Object get(Key key) throws PageException { 418 Object res = get(key,NULL); 419 if(res!=NULL) return res; 420 throw StructImpl.invalidKey(this, key); 421 } 422 public Object get(PageContext pc, String key, Object defaultValue) { 423 return get(key,defaultValue); 424 } 425 426 public Object get(PageContext pc, Key key, Object defaultValue) { 427 return get(key,defaultValue); 428 } 429 430 public Object get(PageContext pc, String key) throws PageException { 431 return get(key); 432 } 433 434 public Object get(PageContext pc, Key key) throws PageException { 435 return get(key); 436 } 437 public Object call(PageContext pc, Key methodName, Object[] arguments) throws PageException { 438 return call(pc, methodName.getString(), arguments); 439 } 440 /*public Object remove (String key) throws PageException { 441 return remove(KeyImpl.init(key)); 442 }*/ 443 public Object removeEL(Key key) { 444 try { 445 return remove(key); 446 } catch (PageException e) { 447 return null; 448 } 449 } 450 }