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    }