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