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    }