View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.view.facelets.impl;
20  
21  import java.io.IOException;
22  import java.net.URL;
23  import java.util.ArrayList;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.LinkedList;
27  import java.util.List;
28  import java.util.Set;
29  
30  import javax.el.ELContext;
31  import javax.el.ELException;
32  import javax.el.ELResolver;
33  import javax.el.ExpressionFactory;
34  import javax.el.FunctionMapper;
35  import javax.el.ValueExpression;
36  import javax.el.VariableMapper;
37  import javax.faces.FacesException;
38  import javax.faces.application.Resource;
39  import javax.faces.component.UIComponent;
40  import javax.faces.context.FacesContext;
41  import javax.faces.view.facelets.FaceletContext;
42  import javax.faces.view.facelets.FaceletException;
43  
44  import org.apache.myfaces.view.facelets.AbstractFacelet;
45  import org.apache.myfaces.view.facelets.AbstractFaceletContext;
46  import org.apache.myfaces.view.facelets.ELExpressionCacheMode;
47  import org.apache.myfaces.view.facelets.FaceletCompositionContext;
48  import org.apache.myfaces.view.facelets.PageContext;
49  import org.apache.myfaces.view.facelets.TemplateClient;
50  import org.apache.myfaces.view.facelets.TemplateContext;
51  import org.apache.myfaces.view.facelets.TemplateManager;
52  import org.apache.myfaces.view.facelets.el.DefaultVariableMapper;
53  import org.apache.myfaces.view.facelets.el.VariableMapperBase;
54  import org.apache.myfaces.view.facelets.tag.jsf.core.AjaxHandler;
55  
56  /**
57   * Default FaceletContext implementation.
58   * 
59   * A single FaceletContext is used for all Facelets involved in an invocation of
60   * {@link org.apache.myfaces.view.facelets.Facelet#apply(FacesContext, UIComponent)
61   * Facelet#apply(FacesContext, UIComponent)}. This
62   * means that included Facelets are treated the same as the JSP include directive.
63   * 
64   * @author Jacob Hookom
65   * @version $Id$
66   */
67  final class DefaultFaceletContext extends AbstractFaceletContext
68  {
69      private final FacesContext _faces;
70  
71      private final ELContext _ctx;
72  
73      private final AbstractFacelet _facelet;
74      private final List<AbstractFacelet> _faceletHierarchy;
75  
76      private VariableMapper _varMapper;
77      private final DefaultVariableMapper _defaultVarMapper;
78      private VariableMapperBase _varMapperBase;
79  
80      private FunctionMapper _fnMapper;
81  
82      //private final Map<String, Integer> _ids;
83      //private final Map<Integer, Integer> _prefixes;
84      private String _prefix;
85  
86      private StringBuilder _uniqueIdBuilder;
87  
88      //private final LinkedList<TemplateManager> _clients;
89      
90      private final FaceletCompositionContext _mctx;
91      
92      private LinkedList<AjaxHandler> _ajaxHandlerStack;
93      
94      private final List<TemplateContext> _isolatedTemplateContext;
95      
96      private int _currentTemplateContext;
97      
98      private ELExpressionCacheMode _elExpressionCacheMode;
99      
100     private boolean _isCacheELExpressions;
101 
102     private final List<PageContext> _isolatedPageContext;
103     
104     public DefaultFaceletContext(DefaultFaceletContext ctx,
105             AbstractFacelet facelet, boolean ccWrap)
106     {
107         _ctx = ctx._ctx;
108         //_ids = ctx._ids;
109         //_prefixes = ctx._prefixes;
110         //_clients = ctx._clients;
111         _faces = ctx._faces;
112         _fnMapper = ctx._fnMapper;
113         _varMapper = ctx._varMapper;
114         _defaultVarMapper = ctx._defaultVarMapper;
115         _varMapperBase = ctx._varMapperBase;
116         _faceletHierarchy = new ArrayList<AbstractFacelet>(ctx._faceletHierarchy
117                 .size() + 1);
118         _faceletHierarchy.addAll(ctx._faceletHierarchy);
119         _faceletHierarchy.add(facelet);
120         _facelet = facelet;
121         _mctx = ctx._mctx;
122         
123         if (ccWrap)
124         {
125             // Each time a composite component is being applied, a new
126             // ajax stack should be created, and f:ajax tags outside the
127             // composite component should be ignored.
128             _ajaxHandlerStack = null;
129         }
130         else
131         {
132             // It is a template include, the current ajax stack should be
133             // preserved.
134             _ajaxHandlerStack = ctx._ajaxHandlerStack;
135         }
136         
137         // It is not necessary to create a copy of this array, because we always use
138         // pushTemplateContext(TemplateContext) / popTemplateContext() and
139         // pushCompositeComponentClient(final TemplateClient client) / popCompositeComponentClient()
140         // in pairs.
141         //_isolatedTemplateContext = new ArrayList<TemplateContext>(ctx._isolatedTemplateContext.size()+1);
142         //for (int i = 0; i <= ctx._currentTemplateContext; i++)
143         //{
144         //    _isolatedTemplateContext.add(ctx._isolatedTemplateContext.get(i));
145         //}
146         _isolatedTemplateContext = ctx._isolatedTemplateContext;
147         _currentTemplateContext = ctx._currentTemplateContext;
148         
149         _isolatedPageContext = ctx._isolatedPageContext;
150         
151         _elExpressionCacheMode = ctx._elExpressionCacheMode;
152         _isCacheELExpressions = ctx._isCacheELExpressions;
153 
154     }
155 
156     public DefaultFaceletContext(FacesContext faces, AbstractFacelet facelet, FaceletCompositionContext mctx)
157     {
158         _ctx = faces.getELContext();
159         //_ids = new HashMap<String, Integer>();
160         //_prefixes = new HashMap<Integer, Integer>();
161         //_clients = new LinkedList<TemplateManager>();
162         _faces = faces;
163         _fnMapper = _ctx.getFunctionMapper();
164         _varMapper = _ctx.getVariableMapper();
165         if (_varMapper == null)
166         {
167             _defaultVarMapper = new DefaultVariableMapper();
168             _varMapper = _defaultVarMapper;
169             _varMapperBase = _defaultVarMapper;
170         }
171         else
172         {
173             _defaultVarMapper = new DefaultVariableMapper(_varMapper);
174             _varMapper = _defaultVarMapper;
175             _varMapperBase = _defaultVarMapper;
176         }
177         
178         _faceletHierarchy = new ArrayList<AbstractFacelet>(1);
179         _faceletHierarchy.add(facelet);
180         _facelet = facelet;
181         _mctx = mctx;
182         
183         _isolatedTemplateContext = new ArrayList<TemplateContext>(1);
184         _isolatedTemplateContext.add(new TemplateContextImpl());
185         _currentTemplateContext = 0;
186         _defaultVarMapper.setTemplateContext(_isolatedTemplateContext.get(_currentTemplateContext));
187         
188         _isolatedPageContext = new ArrayList<PageContext>(8);
189         
190         _elExpressionCacheMode = mctx.getELExpressionCacheMode();
191         _isCacheELExpressions = !ELExpressionCacheMode.noCache.equals(_elExpressionCacheMode);
192     }
193 
194     /**
195      * {@inheritDoc}
196      */
197     @Override
198     public FacesContext getFacesContext()
199     {
200         return _faces;
201     }
202 
203     /**
204      * {@inheritDoc}
205      */
206     @Override
207     public ExpressionFactory getExpressionFactory()
208     {
209         return _facelet.getExpressionFactory();
210     }
211 
212     /**
213      * {@inheritDoc}
214      */
215     @Override
216     public void setVariableMapper(VariableMapper varMapper)
217     {
218         // Assert.param("varMapper", varMapper);
219         _varMapper = varMapper;
220         _varMapperBase = (_varMapper instanceof VariableMapperBase) ? (VariableMapperBase) varMapper : null;
221     }
222 
223     /**
224      * {@inheritDoc}
225      */
226     @Override
227     public void setFunctionMapper(FunctionMapper fnMapper)
228     {
229         // Assert.param("fnMapper", fnMapper);
230         _fnMapper = fnMapper;
231     }
232 
233     /**
234      * {@inheritDoc}
235      */
236     @Override
237     public void includeFacelet(UIComponent parent, String relativePath)
238             throws IOException
239     {
240         _facelet.include(this, parent, relativePath);
241     }
242 
243     /**
244      * {@inheritDoc}
245      */
246     @Override
247     public FunctionMapper getFunctionMapper()
248     {
249         return _fnMapper;
250     }
251 
252     /**
253      * {@inheritDoc}
254      */
255     @Override
256     public VariableMapper getVariableMapper()
257     {
258         return _varMapper;
259     }
260 
261     /**
262      * {@inheritDoc}
263      */
264     @Override
265     @SuppressWarnings("unchecked")
266     public Object getContext(Class key)
267     {
268         return _ctx.getContext(key);
269     }
270 
271     /**
272      * {@inheritDoc}
273      */
274     @Override
275     @SuppressWarnings("unchecked")
276     public void putContext(Class key, Object contextObject)
277     {
278         _ctx.putContext(key, contextObject);
279     }
280 
281     private void initPrefix()
282     {
283         if (_prefix == null)
284         {
285             _uniqueIdBuilder = new StringBuilder(
286                     _faceletHierarchy.size() * 30);
287             for (int i = 0; i < _faceletHierarchy.size(); i++)
288             {
289                 AbstractFacelet facelet = _faceletHierarchy.get(i);
290                 _uniqueIdBuilder.append(facelet.getFaceletId());
291             }
292 
293             // Integer prefixInt = new Integer(builder.toString().hashCode());
294             // -= Leonardo Uribe =- if the previous formula is used, it is possible that
295             // negative values are introduced. The presence of '-' char causes problems
296             // with htmlunit 2.4 or lower, so in order to prevent it it is better to use
297             // only positive values instead.
298             // Take into account CompilationManager.nextTagId() uses Math.abs too.
299             _prefix = Integer.toString(Math.abs(_uniqueIdBuilder.toString().hashCode()));
300         }
301     }
302     
303     /**
304      * {@inheritDoc}
305      */
306     @Override
307     public String generateUniqueId(String base)
308     {
309         initPrefix();
310 
311         _uniqueIdBuilder.setLength(0);
312         // getFaceletCompositionContext().generateUniqueId() is the one who ensures
313         // the final id will be unique, but prefix and base ensure it will be unique
314         // per facelet because prefix is calculated from faceletHierarchy and base is
315         // related to the tagId, which depends on the location.
316         //_uniqueIdBuilder.append(getFaceletCompositionContext().generateUniqueId());
317         
318         String uniqueIdFromIterator = getFaceletCompositionContext().getUniqueIdFromIterator();
319         if (uniqueIdFromIterator == null)
320         {
321             getFaceletCompositionContext().generateUniqueId(_uniqueIdBuilder);
322             // Since two different facelets are used to build the metadata, it is necessary
323             // to trim the "base" part from the returned unique id, to ensure the components will be
324             // refreshed properly. Note the "base" part is the one that allows to ensure
325             // uniqueness between two different facelets with the same <f:metadata>, but since by 
326             // spec view metadata sections cannot live on template client facelets, this case is
327             // just not possible. 
328             // MYFACES-3709 It was also noticed that in some cases, the prefix should also
329             // be excluded from the id. The prefix is included if the metadata section is
330             // applied inside an included section (by ui:define and ui:insert for example).
331             if (!getFaceletCompositionContext().isInMetadataSection())
332             {
333                 _uniqueIdBuilder.append("_");
334                 _uniqueIdBuilder.append(_prefix);
335                 _uniqueIdBuilder.append("_");
336                 _uniqueIdBuilder.append(base);
337             }
338             uniqueIdFromIterator = _uniqueIdBuilder.toString();
339             getFaceletCompositionContext().addUniqueId(uniqueIdFromIterator);
340             return uniqueIdFromIterator;
341         }
342         else
343         {
344             getFaceletCompositionContext().incrementUniqueId();
345             return uniqueIdFromIterator;
346         }
347     }
348     
349     public String generateUniqueFaceletTagId(String count, String base)    
350     {
351         initPrefix();
352         _uniqueIdBuilder.setLength(0);
353         _uniqueIdBuilder.append(count);
354         _uniqueIdBuilder.append("_");
355         _uniqueIdBuilder.append(_prefix);
356         _uniqueIdBuilder.append("_");
357         _uniqueIdBuilder.append(base);
358         return _uniqueIdBuilder.toString();
359     }
360 
361     /**
362      * {@inheritDoc}
363      */
364     @Override
365     public Object getAttribute(String name)
366     {
367         if (_varMapper != null)
368         {
369             ValueExpression ve = _varMapper.resolveVariable(name);
370             if (ve != null)
371             {
372                 return ve.getValue(this);
373             }
374         }
375         return null;
376     }
377 
378     /**
379      * {@inheritDoc}
380      */
381     @Override
382     public void setAttribute(String name, Object value)
383     {
384         if (_varMapper != null)
385         {
386             if (value == null)
387             {
388                 _varMapper.setVariable(name, null);
389             }
390             else
391             {
392                 _varMapper.setVariable(name, _facelet.getExpressionFactory()
393                         .createValueExpression(value, Object.class));
394             }
395         }
396     }
397 
398     /**
399      * {@inheritDoc}
400      */
401     @Override
402     public void includeFacelet(UIComponent parent, URL absolutePath)
403             throws IOException, FacesException, ELException
404     {
405         _facelet.include(this, parent, absolutePath);
406     }
407 
408     /**
409      * {@inheritDoc}
410      */
411     @Override
412     public ELResolver getELResolver()
413     {
414         return _ctx.getELResolver();
415     }
416 
417     //Begin methods from AbstractFaceletContext
418 
419     @Override
420     public TemplateManager popClient(TemplateClient client)
421     {
422         //if (!this._clients.isEmpty())
423         //{
424         //    Iterator<TemplateManager> itr = this._clients.iterator();
425         //    while (itr.hasNext())
426         //    {
427         //        if (itr.next().equals(client))
428         //        {
429         //            itr.remove();
430         //            return;
431         //        }
432         //    }
433         //}
434         //throw new IllegalStateException(client + " not found");
435         //return _clients.removeFirst();
436         return _isolatedTemplateContext.get(_currentTemplateContext).popClient(this);
437     }
438 
439     @Override
440     public void pushClient(final TemplateClient client)
441     {
442         //this._clients.add(0, new TemplateManager(this._facelet, client, true));
443         //_clients.addFirst(new TemplateManagerImpl(this._facelet, client, true));
444         _isolatedTemplateContext.get(_currentTemplateContext).pushClient(this, this._facelet, client);
445     }
446 
447     public TemplateManager popExtendedClient(TemplateClient client)
448     {
449         //return _clients.removeLast();
450         return _isolatedTemplateContext.get(_currentTemplateContext).popExtendedClient(this);
451     }
452     
453     @Override
454     public void extendClient(final TemplateClient client)
455     {
456         //this._clients.add(new TemplateManager(this._facelet, client, false));
457         //_clients.addLast(new TemplateManagerImpl(this._facelet, client, false));
458         _isolatedTemplateContext.get(_currentTemplateContext).extendClient(this, this._facelet, client);
459     }
460 
461     @Override
462     public boolean includeDefinition(UIComponent parent, String name)
463             throws IOException, FaceletException, FacesException, ELException
464     {
465         //boolean found = false;
466         //TemplateManager client;
467         //for (int i = 0, size = this._clients.size(); i < size && !found; i++)
468         //{
469         //    client = ((TemplateManager) this._clients.get(i));
470         //    if (client.equals(this._facelet))
471         //        continue;
472         //    found = client.apply(this, parent, name);
473         //}
474         //return found;
475         return _isolatedTemplateContext.get(_currentTemplateContext).includeDefinition(
476                 this, this._facelet, parent, name);
477     }
478 
479     /*
480     private final static class TemplateManagerImpl extends TemplateManager implements TemplateClient
481     {
482         private final DefaultFacelet _owner;
483 
484         private final TemplateClient _target;
485 
486         private final boolean _root;
487 
488         private final Set<String> _names = new HashSet<String>();
489 
490         public TemplateManagerImpl(DefaultFacelet owner, TemplateClient target,
491                 boolean root)
492         {
493             this._owner = owner;
494             this._target = target;
495             this._root = root;
496         }
497 
498         public boolean apply(FaceletContext ctx, UIComponent parent, String name)
499                 throws IOException, FacesException, FaceletException,
500                 ELException
501         {
502             String testName = (name != null) ? name : "facelets._NULL_DEF_";
503             if (this._names.contains(testName))
504             {
505                 return false;
506             }
507             else
508             {
509                 this._names.add(testName);
510                 boolean found = false;
511                 found = this._target
512                         .apply(new DefaultFaceletContext(
513                                 (DefaultFaceletContext) ctx, this._owner, false),
514                                 parent, name);
515                 this._names.remove(testName);
516                 return found;
517             }
518         }
519 
520         public boolean equals(Object o)
521         {
522             // System.out.println(this.owner.getAlias() + " == " +
523             // ((DefaultFacelet) o).getAlias());
524             return this._owner == o || this._target == o;
525         }
526 
527         public boolean isRoot()
528         {
529             return this._root;
530         }
531     }*/
532 
533     /*
534     @Override
535     public TemplateManager popCompositeComponentClient(boolean cleanClientStack)
536     {
537         //if (!this._compositeComponentClients.isEmpty())
538         //{
539             //if (cleanClientStack)
540             //{
541             //    _clientsStack.get(_currentClientStack).clear();
542             //}
543             //_currentClientStack--;
544             //return this._compositeComponentClients.remove(0);
545         //}
546         if (_currentTemplateContext > 0)
547         {
548             TemplateManager tm = _isolatedTemplateContext.get(_currentTemplateContext).getCompositeComponentClient();
549             if (cleanClientStack)
550             {
551                 _isolatedTemplateContext.get(_currentTemplateContext).clear();
552             }
553             _currentTemplateContext--;
554             return tm;
555         }
556         return null;
557     }
558     
559 
560     @Override
561     public void pushCompositeComponentClient(final TemplateClient client)
562     {
563         //this._compositeComponentClients.add(0, new CompositeComponentTemplateManager(this._facelet, client));
564         //if (_currentClientStack + 1 <= _clientsStack.size())
565         //{
566         //    _clientsStack.add(new LinkedList<TemplateManager>());
567         //}
568         //_currentClientStack++;
569         if (_currentTemplateContext + 1 <= _isolatedTemplateContext.size())
570         {
571             _isolatedTemplateContext.add(new IsolatedTemplateContextImpl());
572         }
573         _currentTemplateContext++;
574         _isolatedTemplateContext.get(_currentTemplateContext).setCompositeComponentClient(
575             new CompositeComponentTemplateManager(this._facelet, client));
576     }
577     
578     @Override
579     public void pushCompositeComponentClient(final TemplateManager client)
580     {
581         //this._compositeComponentClients.add(0, client);
582         //if (_currentClientStack + 1 < _clientsStack.size())
583         //{
584         //    _clientsStack.add(new LinkedList<TemplateManager>());
585         //}
586         //_currentClientStack++;
587         if (_currentTemplateContext + 1 < _isolatedTemplateContext.size())
588         {
589             _isolatedTemplateContext.add(new IsolatedTemplateContextImpl());
590         }
591         _currentTemplateContext++;
592         _isolatedTemplateContext.get(_currentTemplateContext).setCompositeComponentClient(client);
593     }*/
594     
595     @Override
596     public void pushCompositeComponentClient(final TemplateClient client)
597     {
598         TemplateContext itc = new TemplateContextImpl();
599         itc.setCompositeComponentClient(
600                 new CompositeComponentTemplateManager(this._facelet, client, getPageContext()));
601         _isolatedTemplateContext.add(itc);
602         _currentTemplateContext++;
603         _defaultVarMapper.setTemplateContext(itc);
604     }
605     
606     @Override
607     public void popCompositeComponentClient()
608     {
609         if (_currentTemplateContext > 0)
610         {
611             _isolatedTemplateContext.remove(_currentTemplateContext);
612             _currentTemplateContext--;
613             _defaultVarMapper.setTemplateContext(_isolatedTemplateContext.get(_currentTemplateContext));
614         }
615     }
616     
617     @Override
618     public void pushTemplateContext(TemplateContext client)
619     {
620         _isolatedTemplateContext.add(client);
621         _currentTemplateContext++;
622         _defaultVarMapper.setTemplateContext(client);
623     }    
624 
625     
626     @Override
627     public TemplateContext popTemplateContext()
628     {
629         if (_currentTemplateContext > 0)
630         {
631             TemplateContext itc = _isolatedTemplateContext.get(_currentTemplateContext);
632             _isolatedTemplateContext.remove(_currentTemplateContext);
633             _currentTemplateContext--;
634             _defaultVarMapper.setTemplateContext(_isolatedTemplateContext.get(_currentTemplateContext));
635             return itc;
636         }
637         return null;
638     }
639     
640     @Override
641     public TemplateContext getTemplateContext()
642     {
643         return _isolatedTemplateContext.get(_currentTemplateContext);
644     }
645 
646     @Override
647     public boolean includeCompositeComponentDefinition(UIComponent parent, String name)
648             throws IOException, FaceletException, FacesException, ELException
649     {
650         //boolean found = false;
651         //TemplateManager client;
652 
653         //for (int i = 0, size = this._compositeComponentClients.size(); i < size && !found; i++)
654         //{
655         //    client = ((TemplateManager) this._compositeComponentClients.get(i));
656         //    if (client.equals(this._facelet))
657         //        continue;
658         //    found = client.apply(this, parent, name);
659         //}
660 
661         //return found;
662         TemplateClient ccClient = _isolatedTemplateContext.get(_currentTemplateContext).getCompositeComponentClient();
663         if (ccClient != null)
664         {
665             return ccClient.apply(this, parent, name);
666         }
667         return false;
668     }
669     
670     private final static class CompositeComponentTemplateManager extends TemplateManager implements TemplateClient
671     {
672         private final AbstractFacelet _owner;
673 
674         protected final TemplateClient _target;
675 
676         private final Set<String> _names = new HashSet<String>();
677         
678         private final PageContext _pageContext;
679 
680         public CompositeComponentTemplateManager(AbstractFacelet owner, TemplateClient target, PageContext pageContext)
681         {
682             this._owner = owner;
683             this._target = target;
684             this._pageContext = pageContext;
685         }
686 
687         public boolean apply(FaceletContext ctx, UIComponent parent, String name)
688                 throws IOException, FacesException, FaceletException,
689                 ELException
690         {
691             String testName = (name != null) ? name : "facelets._NULL_DEF_";
692             if (this._names.contains(testName))
693             {
694                 return false;
695             }
696             else
697             {
698                 this._names.add(testName);
699                 boolean found = false;
700                 AbstractFaceletContext actx = new DefaultFaceletContext(
701                         (DefaultFaceletContext) ctx, this._owner, false);
702                 ctx.getFacesContext().getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, actx);
703                 try
704                 {
705                     actx.pushPageContext(this._pageContext);
706                     found = this._target
707                             .apply(actx,
708                                     parent, name);
709                 }
710                 finally
711                 {
712                     actx.popPageContext();
713                 }
714                 ctx.getFacesContext().getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, ctx);
715                 this._names.remove(testName);
716                 return found;
717             }
718         }
719 
720         public boolean equals(Object o)
721         {
722             // System.out.println(this.owner.getAlias() + " == " +
723             // ((DefaultFacelet) o).getAlias());
724             return this._owner == o || this._target == o;
725         }
726 
727         @Override
728         public int hashCode()
729         {
730             int result = _owner != null ? _owner.hashCode() : 0;
731             result = 31 * result + (_target != null ? _target.hashCode() : 0);
732             return result;
733         }
734     }
735     
736     @Override
737     public void pushPageContext(PageContext client)
738     {
739         _isolatedPageContext.add(client);
740         _defaultVarMapper.setPageContext(client);
741     }    
742 
743     @Override
744     public PageContext popPageContext()
745     {
746         if (!_isolatedPageContext.isEmpty())
747         {
748             int currentPageContext = _isolatedPageContext.size()-1;
749             PageContext itc = _isolatedPageContext.get(currentPageContext);
750             _isolatedPageContext.remove(currentPageContext);
751             if (!_isolatedPageContext.isEmpty())
752             {
753                 _defaultVarMapper.setPageContext(getPageContext());
754             }
755             else
756             {
757                 _defaultVarMapper.setPageContext(null);
758             }
759             return itc;
760         }
761         return null;
762     }
763     
764     @Override
765     public PageContext getPageContext()
766     {
767         return _isolatedPageContext.get(_isolatedPageContext.size()-1);
768     }
769     
770     //End methods from AbstractFaceletContext
771     
772     /**
773      * {@inheritDoc}
774      */
775     @Override
776     public boolean isPropertyResolved()
777     {
778         return _ctx.isPropertyResolved();
779     }
780 
781     /**
782      * {@inheritDoc}
783      */
784     @Override
785     public void setPropertyResolved(boolean resolved)
786     {
787         _ctx.setPropertyResolved(resolved);
788     }
789 
790     @Override
791     public void applyCompositeComponent(UIComponent parent, Resource resource)
792             throws IOException, FaceletException, FacesException, ELException
793     {
794         _facelet.applyCompositeComponent(this, parent, resource);
795     }
796 
797     @Override
798     public Iterator<AjaxHandler> getAjaxHandlers()
799     {
800         if (_ajaxHandlerStack != null && !_ajaxHandlerStack.isEmpty())
801         {
802             return _ajaxHandlerStack.iterator();
803         }
804         return null;
805     }
806 
807     @Override
808     public void popAjaxHandlerToStack()
809     {
810         if (_ajaxHandlerStack != null && !_ajaxHandlerStack.isEmpty())
811         {
812             _ajaxHandlerStack.removeFirst();
813         }
814     }
815 
816     @Override
817     public void pushAjaxHandlerToStack(
818             AjaxHandler parent)
819     {
820         if (_ajaxHandlerStack == null)
821         {
822             _ajaxHandlerStack = new LinkedList<AjaxHandler>();
823         }
824 
825         _ajaxHandlerStack.addFirst(parent);
826     }
827 
828     @Override
829     public boolean isBuildingCompositeComponentMetadata()
830     {
831         return _facelet.isBuildingCompositeComponentMetadata();
832     }
833     
834     public FaceletCompositionContext getFaceletCompositionContext()
835     {
836         return _mctx;
837     }
838     
839     public boolean isAnyFaceletsVariableResolved()
840     {
841         //if (isAllowCacheELExpressions() && _varMapperBase != null)
842         if (_varMapperBase != null)
843         {
844             return _varMapperBase.isAnyFaceletsVariableResolved();
845         }
846         return true;
847     }
848     
849     public boolean isAllowCacheELExpressions()
850     {
851         return _isCacheELExpressions && getTemplateContext().isAllowCacheELExpressions() 
852                 && getPageContext().isAllowCacheELExpressions();
853     }
854     
855     public void beforeConstructELExpression()
856     {
857         //if (isAllowCacheELExpressions() && _varMapperBase != null)
858         if (_varMapperBase != null)
859         {
860             _varMapperBase.beforeConstructELExpression();
861         }
862     }
863     
864     public void afterConstructELExpression()
865     {
866         //if (isAllowCacheELExpressions() && _varMapperBase != null)
867         if (_varMapperBase != null)
868         {
869             _varMapperBase.afterConstructELExpression();
870         }
871     }
872     
873     public ELExpressionCacheMode getELExpressionCacheMode()
874     {
875         return _elExpressionCacheMode;
876     }
877     
878 }