001 package railo.runtime; 002 003 import java.util.HashMap; 004 import java.util.Iterator; 005 import java.util.Map; 006 007 import railo.runtime.component.Member; 008 import railo.runtime.dump.DumpData; 009 import railo.runtime.dump.DumpProperties; 010 import railo.runtime.engine.ThreadLocalPageContext; 011 import railo.runtime.exp.ExpressionException; 012 import railo.runtime.exp.PageException; 013 import railo.runtime.op.Duplicator; 014 import railo.runtime.type.Collection; 015 import railo.runtime.type.KeyImpl; 016 import railo.runtime.type.Struct; 017 import railo.runtime.type.StructImpl; 018 import railo.runtime.type.UDF; 019 import railo.runtime.type.dt.DateTime; 020 import railo.runtime.type.it.KeyIterator; 021 import railo.runtime.type.util.ComponentUtil; 022 import railo.runtime.type.util.StructSupport; 023 import railo.runtime.type.util.StructUtil; 024 025 public class ComponentScopeShadow extends StructSupport implements ComponentScope { 026 027 private static final long serialVersionUID = 4930100230796574243L; 028 029 private final ComponentImpl component; 030 private static final int access=Component.ACCESS_PRIVATE; 031 private final Map<Key,Object> shadow; 032 033 034 /** 035 * Constructor of the class 036 * @param component 037 * @param shadow 038 */ 039 public ComponentScopeShadow(ComponentImpl component, Map<Key,Object> shadow) { 040 this.component=component; 041 this.shadow=shadow; 042 043 } 044 045 /** 046 * Constructor of the class 047 * @param component 048 * @param shadow 049 */ 050 public ComponentScopeShadow(ComponentImpl component, ComponentScopeShadow scope,boolean cloneShadow) { 051 this.component=component; 052 this.shadow=cloneShadow?Duplicator.duplicateMap(scope.shadow,new HashMap<Key,Object>(), false):scope.shadow; 053 } 054 055 056 /** 057 * @see railo.runtime.ComponentScope#getComponent() 058 */ 059 public ComponentPro getComponent() { 060 return component; 061 } 062 063 /** 064 * @see railo.runtime.type.Scope#getType() 065 */ 066 public int getType() { 067 return SCOPE_VARIABLES; 068 } 069 070 /** 071 * @see railo.runtime.type.Scope#getTypeAsString() 072 */ 073 public String getTypeAsString() { 074 return "variables"; 075 } 076 077 /** 078 * @see railo.runtime.type.Scope#initialize(railo.runtime.PageContext) 079 */ 080 public void initialize(PageContext pc) {} 081 082 /** 083 * @see railo.runtime.type.Scope#isInitalized() 084 */ 085 public boolean isInitalized() { 086 return component.isInitalized(); 087 } 088 089 /** 090 * @see railo.runtime.type.Scope#release() 091 */ 092 public void release() {} 093 094 /** 095 * @see railo.runtime.type.Collection#clear() 096 */ 097 public void clear() { 098 shadow.clear(); 099 } 100 101 /** 102 * 103 * @see railo.runtime.type.Collection#containsKey(railo.runtime.type.Collection.Key) 104 */ 105 public boolean containsKey(Collection.Key key) { 106 return get(key,null)!=null; 107 } 108 109 /** 110 * 111 * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key) 112 */ 113 public Object get(Key key) throws PageException { 114 Object o = get(key,null); 115 if(o!=null) return o; 116 throw new ExpressionException("Component ["+component.getCallName()+"] has no accessible Member with name ["+key+"]"); 117 } 118 119 /** 120 * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key, java.lang.Object) 121 */ 122 public Object get(Key key, Object defaultValue) { 123 if(key.equalsIgnoreCase(KeyImpl.SUPER)) { 124 return SuperComponent.superInstance((ComponentImpl)ComponentUtil.getActiveComponent(ThreadLocalPageContext.get(),component)._base()); 125 } 126 if(key.equalsIgnoreCase(KeyImpl.THIS)) return component; 127 128 Object o=shadow.get(key); 129 if(o!=null) return o; 130 return defaultValue; 131 } 132 133 /** 134 * @see railo.runtime.type.Collection#keyIterator() 135 */ 136 public Iterator keyIterator() { 137 return new KeyIterator(keys()); 138 } 139 140 /** 141 * @see railo.runtime.type.Collection#keysAsString() 142 */ 143 public String[] keysAsString() { 144 String[] keys=new String[shadow.size()+1]; 145 Iterator<Key> it = shadow.keySet().iterator(); 146 int index=0; 147 while(it.hasNext()) { 148 keys[index++]=it.next().getString(); 149 } 150 keys[index]=KeyImpl.THIS_UC.getString(); 151 return keys; 152 } 153 154 /** 155 * @see railo.runtime.type.Collection#keys() 156 */ 157 public Collection.Key[] keys() { 158 Collection.Key[] keys=new Collection.Key[shadow.size()+1]; 159 Iterator<Key> it = shadow.keySet().iterator(); 160 int index=0; 161 while(it.hasNext()) { 162 keys[index++]=it.next(); 163 } 164 keys[index]=KeyImpl.THIS_UC; 165 return keys; 166 } 167 168 /** 169 * @see railo.runtime.type.Collection#remove(railo.runtime.type.Collection.Key) 170 */ 171 public Object remove(Collection.Key key) throws PageException { 172 if(key.equalsIgnoreCase(KeyImpl.THIS) || key.equalsIgnoreCase(KeyImpl.SUPER)) 173 throw new ExpressionException("key ["+key.getString()+"] is part from component and can't be removed"); 174 175 Object o=shadow.remove(key); 176 if(o!=null) return o; 177 throw new ExpressionException("can't remove key ["+key.getString()+"] from struct, key doesn't exists "); 178 } 179 180 181 182 public Object removeEL(Key key) { 183 if(key.equalsIgnoreCase(KeyImpl.THIS) || key.equalsIgnoreCase(KeyImpl.SUPER))return null; 184 return shadow.remove(key); 185 } 186 187 /** 188 * @see railo.runtime.type.Collection#set(railo.runtime.type.Collection.Key, java.lang.Object) 189 */ 190 public Object set(Collection.Key key, Object value) { 191 if(key.equalsIgnoreCase(KeyImpl.THIS) || key.equalsIgnoreCase(KeyImpl.SUPER)) return value; 192 193 if(!component.afterConstructor && value instanceof UDF) { 194 component.addConstructorUDF(key,(UDF)value); 195 } 196 shadow.put(key, value); 197 return value; 198 } 199 200 /** 201 * @see railo.runtime.type.Collection#setEL(railo.runtime.type.Collection.Key, java.lang.Object) 202 */ 203 public Object setEL(Collection.Key key, Object value) { 204 return set(key, value); 205 } 206 207 /** 208 * @see railo.runtime.type.Collection#size() 209 */ 210 public int size() { 211 return keysAsString().length; 212 } 213 214 /** 215 * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int) 216 */ 217 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 218 return StructUtil.toDumpTable(this, "Variable Scope (of Component)", pageContext, maxlevel, dp); 219 } 220 221 /** 222 * 223 * @see railo.runtime.op.Castable#castToBooleanValue() 224 */ 225 public boolean castToBooleanValue() throws PageException { 226 throw new ExpressionException("Can't cast Complex Object Type to a boolean value"); 227 } 228 229 /** 230 * @see railo.runtime.op.Castable#castToBoolean(java.lang.Boolean) 231 */ 232 public Boolean castToBoolean(Boolean defaultValue) { 233 return defaultValue; 234 } 235 236 /** 237 * @see railo.runtime.op.Castable#castToDateTime() 238 */ 239 public DateTime castToDateTime() throws PageException { 240 throw new ExpressionException("Can't cast Complex Object Type to a Date Object"); 241 } 242 243 /** 244 * @see railo.runtime.op.Castable#castToDateTime(railo.runtime.type.dt.DateTime) 245 */ 246 public DateTime castToDateTime(DateTime defaultValue) { 247 return defaultValue; 248 } 249 250 /** 251 * @see railo.runtime.op.Castable#castToDoubleValue() 252 */ 253 public double castToDoubleValue() throws PageException { 254 throw new ExpressionException("Can't cast Complex Object Type to a numeric value"); 255 } 256 257 /** 258 * @see railo.runtime.op.Castable#castToDoubleValue(double) 259 */ 260 public double castToDoubleValue(double defaultValue) { 261 return defaultValue; 262 } 263 264 /** 265 * @see railo.runtime.op.Castable#castToString() 266 */ 267 public String castToString() throws PageException { 268 throw new ExpressionException("Can't cast Complex Object Type to a String"); 269 } 270 271 /** 272 * @see railo.runtime.type.util.StructSupport#castToString(java.lang.String) 273 */ 274 public String castToString(String defaultValue) { 275 return defaultValue; 276 } 277 278 /** 279 * @see railo.runtime.op.Castable#compare(boolean) 280 */ 281 public int compareTo(boolean b) throws PageException { 282 throw new ExpressionException("can't compare Complex Object with a boolean value"); 283 } 284 285 /** 286 * @see railo.runtime.op.Castable#compareTo(railo.runtime.type.dt.DateTime) 287 */ 288 public int compareTo(DateTime dt) throws PageException { 289 throw new ExpressionException("can't compare Complex Object with a DateTime Object"); 290 } 291 292 /** 293 * @see railo.runtime.op.Castable#compareTo(double) 294 */ 295 public int compareTo(double d) throws PageException { 296 throw new ExpressionException("can't compare Complex Object with a numeric value"); 297 } 298 299 /** 300 * @see railo.runtime.op.Castable#compareTo(java.lang.String) 301 */ 302 public int compareTo(String str) throws PageException { 303 throw new ExpressionException("can't compare Complex Object with a String"); 304 } 305 306 /** 307 * @see railo.runtime.type.Objects#call(railo.runtime.PageContext, java.lang.String, java.lang.Object[]) 308 */ 309 public Object call(PageContext pc, String key, Object[] arguments) throws PageException { 310 return call(pc, KeyImpl.init(key), arguments); 311 } 312 313 public Object call(PageContext pc, Collection.Key key, Object[] arguments) throws PageException { 314 // first check variables 315 Object o=shadow.get(key); 316 if(o instanceof UDF) { 317 return ((UDF)o).call(pc, arguments, false); 318 } 319 320 // then check in component 321 Member m = component.getMember(access, key, false,false); 322 if(m!=null) { 323 if(m instanceof UDF) return ((UDF)m).call(pc, arguments, false); 324 } 325 throw ComponentUtil.notFunction(component, key, m!=null?m.getValue():null,access); 326 } 327 328 /** 329 * @see railo.runtime.type.Objects#callWithNamedValues(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Struct) 330 */ 331 public Object callWithNamedValues(PageContext pc, String key,Struct args) throws PageException { 332 return callWithNamedValues(pc, KeyImpl.init(key), args); 333 } 334 335 public Object callWithNamedValues(PageContext pc, Key key, Struct args) throws PageException { 336 // first check variables 337 Object o=shadow.get(key); 338 if(o instanceof UDF) { 339 return ((UDF)o).callWithNamedValues(pc, args, false); 340 } 341 342 Member m = component.getMember(access, key, false,false); 343 if(m!=null) { 344 if(m instanceof UDF) return ((UDF)m).callWithNamedValues(pc, args, false); 345 throw ComponentUtil.notFunction(component, key, m.getValue(),access); 346 } 347 throw ComponentUtil.notFunction(component, key, null,access); 348 } 349 350 /** 351 * @see railo.runtime.type.Collection#duplicate(boolean) 352 */ 353 public Collection duplicate(boolean deepCopy) { 354 StructImpl sct = new StructImpl(); 355 StructImpl.copy(this, sct, deepCopy); 356 return sct; 357 // MUST muss deepCopy checken 358 //return new ComponentScopeShadow(component,shadow);//new ComponentScopeThis(component.cloneComponentImpl()); 359 } 360 361 362 /** 363 * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, java.lang.String, java.lang.Object) 364 */ 365 public Object get(PageContext pc, String key, Object defaultValue) { 366 return get(key, defaultValue); 367 } 368 369 /** 370 * 371 * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object) 372 */ 373 public Object get(PageContext pc, Key key, Object defaultValue) { 374 return get(key, defaultValue); 375 } 376 377 /** 378 * @see railo.runtime.type.Objects#set(railo.runtime.PageContext, java.lang.String, java.lang.Object) 379 */ 380 public Object set(PageContext pc, String propertyName, Object value) throws PageException { 381 return set(KeyImpl.init(propertyName), value); 382 } 383 384 /** 385 * 386 * @see railo.runtime.type.Objects#set(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object) 387 */ 388 public Object set(PageContext pc, Collection.Key propertyName, Object value) throws PageException { 389 return set(propertyName, value); 390 } 391 392 /** 393 * @see railo.runtime.type.Objects#setEL(railo.runtime.PageContext, java.lang.String, java.lang.Object) 394 */ 395 public Object setEL(PageContext pc, String propertyName, Object value) { 396 return setEL(propertyName, value); 397 } 398 399 /** 400 * @see railo.runtime.type.Objects#setEL(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object) 401 */ 402 public Object setEL(PageContext pc, Collection.Key propertyName, Object value) { 403 return set(propertyName, value); 404 } 405 406 /** 407 * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, java.lang.String) 408 */ 409 public Object get(PageContext pc, String key) throws PageException { 410 return get(key); 411 } 412 413 /** 414 * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, railo.runtime.type.Collection.Key) 415 */ 416 public Object get(PageContext pc, Collection.Key key) throws PageException { 417 return get(key); 418 } 419 420 public Map<Key,Object> getShadow() { 421 return shadow; 422 } 423 }