001 package railo.runtime.type.scope; 002 003 import java.util.Iterator; 004 005 import railo.runtime.PageContext; 006 import railo.runtime.config.NullSupportHelper; 007 import railo.runtime.dump.DumpData; 008 import railo.runtime.dump.DumpProperties; 009 import railo.runtime.dump.DumpTable; 010 import railo.runtime.engine.ThreadLocalPageContext; 011 import railo.runtime.exp.PageException; 012 import railo.runtime.op.Duplicator; 013 import railo.runtime.type.Collection; 014 import railo.runtime.type.Struct; 015 016 public class Closure extends ScopeSupport implements Variables { 017 018 private static final Object NULL = new Object(); 019 private Argument arg; 020 private Local local; 021 private Variables var; 022 private boolean debug; 023 private Undefined und; 024 025 public Closure(PageContext pc,Argument arg, Local local,Variables var ){ 026 super("variables",SCOPE_VARIABLES,Struct.TYPE_REGULAR); 027 arg.setBind(true); 028 local.setBind(true); 029 var.setBind(true); 030 und = pc.undefinedScope(); 031 this.arg=arg; 032 this.local=local; 033 this.var=var; 034 this.debug=pc.getConfig().debug(); 035 } 036 037 @Override 038 public boolean isInitalized() { 039 return true; 040 } 041 042 @Override 043 public void initialize(PageContext pc) { 044 } 045 046 @Override 047 public void release() { 048 } 049 050 @Override 051 public void release(PageContext pc) { 052 } 053 054 @Override 055 public int getType() { 056 return SCOPE_VARIABLES; 057 } 058 059 @Override 060 public String getTypeAsString() { 061 return "variables"; 062 } 063 064 @Override 065 public int size() { 066 return var.size(); 067 } 068 069 @Override 070 public Key[] keys() { 071 return var.keys(); 072 } 073 074 @Override 075 public Object remove(Key key) throws PageException { 076 if(local.containsKey(key)) 077 return local.remove(key); 078 return var.remove(key); 079 } 080 081 @Override 082 public Object removeEL(Key key) { 083 if(local.containsKey(key)) 084 return local.removeEL(key); 085 return var.removeEL(key); 086 } 087 088 @Override 089 public void clear() { 090 var.clear(); 091 } 092 093 @Override 094 public Object get(Key key) throws PageException { 095 Object value = local.get(key,NullSupportHelper.NULL()); 096 if(value!=NullSupportHelper.NULL()) return value; 097 value=arg.get(key,NullSupportHelper.NULL()); 098 if(value!=NullSupportHelper.NULL()) { 099 if(debug) UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),arg.getTypeAsString(), key); 100 return value; 101 } 102 103 value= var.get(key); 104 if(debug) UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),var.getTypeAsString(), key); 105 return value; 106 } 107 108 @Override 109 public Object get(Key key, Object defaultValue) { 110 Object value = local.get(key,NullSupportHelper.NULL()); 111 if(value!=NullSupportHelper.NULL()) return value; 112 value=arg.get(key,NullSupportHelper.NULL()); 113 if(value!=NullSupportHelper.NULL()) { 114 if(debug) UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),arg.getTypeAsString(), key); 115 return value; 116 } 117 value= var.get(key,NullSupportHelper.NULL()); 118 if(value!=NullSupportHelper.NULL()){ 119 if(debug) UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),var.getTypeAsString(), key); 120 return value; 121 } 122 return defaultValue; 123 } 124 125 @Override 126 public Object set(Key key, Object value) throws PageException { 127 if(und.getLocalAlways() || local.containsKey(key)) return local.set(key,value); 128 if(arg.containsKey(key)) { 129 if(debug)UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),arg.getTypeAsString(), key); 130 return arg.set(key,value); 131 } 132 if(debug)UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),var.getTypeAsString(), key); 133 return var.set(key, value); 134 } 135 136 @Override 137 public Object setEL(Key key, Object value) { 138 if(und.getLocalAlways() || local.containsKey(key)) return local.setEL(key,value); 139 if(arg.containsKey(key)) { 140 if(debug)UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),arg.getTypeAsString(), key); 141 return arg.setEL(key,value); 142 } 143 144 if(debug)UndefinedImpl.debugCascadedAccess(ThreadLocalPageContext.get(),var.getTypeAsString(), key); 145 return var.setEL(key,value); 146 } 147 148 @Override 149 public Collection duplicate(boolean deepCopy) { 150 return new Closure(ThreadLocalPageContext.get(),(Argument)Duplicator.duplicate(arg,deepCopy), (Local)Duplicator.duplicate(local,deepCopy), (Variables)Duplicator.duplicate(var,deepCopy)); 151 } 152 153 @Override 154 public boolean containsKey(Key key) { 155 return get(key,NULL)!=NULL; 156 } 157 158 @Override 159 public Iterator<Collection.Key> keyIterator() { 160 return var.keyIterator(); 161 } 162 163 @Override 164 public Iterator<String> keysAsStringIterator() { 165 return var.keysAsStringIterator(); 166 } 167 168 @Override 169 public Iterator<Entry<Key, Object>> entryIterator() { 170 return var.entryIterator(); 171 } 172 173 @Override 174 public Iterator<Object> valueIterator() { 175 return var.valueIterator(); 176 } 177 178 @Override 179 public void setBind(boolean bind) {} 180 181 @Override 182 public boolean isBind() { 183 return true; 184 } 185 186 @Override 187 public DumpData toDumpData(PageContext pageContext, int maxlevel, 188 DumpProperties properties) { 189 190 DumpTable dt= (DumpTable) super.toDumpData(pageContext, maxlevel, properties); 191 dt.setTitle("Closure Variable Scope"); 192 return dt; 193 } 194 195 196 }