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