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.util.Collections;
23  import java.util.Enumeration;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.Iterator;
27  import java.util.LinkedList;
28  import java.util.Map;
29  import java.util.NoSuchElementException;
30  import java.util.Set;
31  
32  import javax.el.ELException;
33  import javax.el.ValueExpression;
34  import javax.faces.FacesException;
35  import javax.faces.component.UIComponent;
36  import javax.faces.view.facelets.FaceletContext;
37  import javax.faces.view.facelets.FaceletException;
38  
39  import org.apache.myfaces.util.AbstractAttributeMap;
40  import org.apache.myfaces.view.facelets.AbstractFacelet;
41  import org.apache.myfaces.view.facelets.AbstractFaceletContext;
42  import org.apache.myfaces.view.facelets.Facelet;
43  import org.apache.myfaces.view.facelets.PageContext;
44  import org.apache.myfaces.view.facelets.TemplateClient;
45  import org.apache.myfaces.view.facelets.TemplateContext;
46  import org.apache.myfaces.view.facelets.TemplateManager;
47  
48  /**
49   * 
50   * @author Leonardo Uribe (latest modification by $Author: lu4242 $)
51   * @version $Revision: 1298129 $ $Date: 2012-03-07 16:26:40 -0500 (Wed, 07 Mar 2012) $
52   * @since 2.0.1
53   */
54  public class TemplateContextImpl extends TemplateContext
55  {
56      /**
57       * This is a dummy instance
58       */
59      private static final TemplateClient INITIAL_TEMPLATE_CLIENT = new InitialTemplateClient();
60      
61      /**
62       * This is a dummy instance
63       */
64      private static final PageContext INITIAL_PAGE_CONTEXT = new InitialPageContext();
65      
66      private final LinkedList<TemplateManagerImpl> _clients;
67      
68      private TemplateManager _compositeComponentClient;
69      
70      private TemplateManagerImpl _lastClient;
71      
72      private boolean _isCacheELExpressions;
73  
74      public TemplateContextImpl()
75      {
76          super();
77          _clients = new LinkedList<TemplateManagerImpl>();
78          // Parameters registered using ui:param now are bound to template manager instances, because
79          // it should follow the same rules as template clients registered here. For example, to resolve
80          // params on nested ui:decorate and ui:composition the same rules applies than for ui:define and
81          // ui:insert. The simplest solution is add a template manager with a dummy template client and
82          // page context, so when a new context is added (like in a ui:include), all params registered go 
83          // to this manager. 
84          _clients.add(new TemplateManagerImpl(null, INITIAL_TEMPLATE_CLIENT, true, INITIAL_PAGE_CONTEXT));
85          _lastClient = _clients.getFirst();
86          _isCacheELExpressions = true;
87      }
88  
89      @Override
90      public TemplateManager popClient(final AbstractFaceletContext actx)
91      {
92          _lastClient = null;
93          return _clients.removeFirst();
94      }
95  
96      @Override
97      public void pushClient(final AbstractFaceletContext actx, final AbstractFacelet owner, final TemplateClient client)
98      {
99          _clients.addFirst(new TemplateManagerImpl(owner, client, true, actx.getPageContext()));
100         _lastClient = _clients.getFirst();
101     }
102 
103     public TemplateManager popExtendedClient(final AbstractFaceletContext actx)
104     {
105         _lastClient = null;
106         return _clients.removeLast();
107     }
108     
109     @Override
110     public void extendClient(final AbstractFaceletContext actx, final AbstractFacelet owner,
111                              final TemplateClient client)
112     {
113         _clients.addLast(new TemplateManagerImpl(owner, client, false, actx.getPageContext()));
114         _lastClient = _clients.getLast();
115     }
116 
117     @Override
118     public boolean includeDefinition(FaceletContext ctx, Facelet owner, UIComponent parent, String name)
119             throws IOException, FaceletException, FacesException, ELException
120     {
121         boolean found = false;
122         TemplateManager client;
123         Iterator<TemplateManagerImpl> itr = _clients.iterator();
124         while (itr.hasNext() && !found)
125         {
126             client = itr.next();
127             if (client.equals(owner))
128             {
129                 continue;
130             }
131             found = client.apply(ctx, parent, name);
132         }
133         return found;
134     }
135     
136     private final static class TemplateManagerImpl extends TemplateManager implements TemplateClient
137     {
138         private final AbstractFacelet _owner;
139 
140         private final TemplateClient _target;
141 
142         private final boolean _root;
143 
144         private Set<String> _names;
145         
146         private final PageContext _pageContext;
147         
148         private Map<String, ValueExpression> _parameters = null;
149 
150         public TemplateManagerImpl(AbstractFacelet owner, TemplateClient target,
151                 boolean root, PageContext pageContext)
152         {
153             this._owner = owner;
154             this._target = target;
155             this._root = root;
156             this._pageContext = pageContext;
157         }
158 
159         public boolean apply(FaceletContext ctx, UIComponent parent, String name)
160                 throws IOException, FacesException, FaceletException,
161                 ELException
162         {
163             String testName = (name != null) ? name : "facelets._NULL_DEF_";
164             if (this._owner == null)
165             {
166                 return false;
167             }
168             if (this._names != null && this._names.contains(testName))
169             {
170                 return false;
171             }
172             else
173             {
174                 if (this._names == null)
175                 {
176                     this._names =  new HashSet<String>();
177                 }
178                 this._names.add(testName);
179                 boolean found = false;
180                 AbstractFaceletContext actx = new DefaultFaceletContext(
181                         (DefaultFaceletContext) ctx, this._owner, false);
182                 ctx.getFacesContext().getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, actx);
183                 try
184                 {
185                     actx.pushPageContext(this._pageContext);
186                     found = this._target
187                             .apply(actx,
188                                     parent, name);
189                 }
190                 finally
191                 {
192                     actx.popPageContext();
193                 }
194                 ctx.getFacesContext().getAttributes().put(FaceletContext.FACELET_CONTEXT_KEY, ctx);
195                 this._names.remove(testName);
196                 return found;
197             }
198         }
199         
200         public Map<String, ValueExpression> getParametersMap()
201         {
202             if (_parameters == null)
203             {
204                 _parameters = new HashMap<String, ValueExpression>();
205             }
206             return _parameters;
207         }
208         
209         public boolean isParamentersMapEmpty()
210         {
211             return _parameters == null ? true : _parameters.isEmpty();
212         }
213 
214         public boolean equals(Object o)
215         {
216             if (this._owner != null)
217             {
218                 return this._owner == o || this._target == o;
219             }
220             else
221             {
222                 return this._target == o;
223             }
224         }
225 
226         @Override
227         public int hashCode()
228         {
229             int result = _owner != null ? _owner.hashCode() : 0;
230             result = 31 * result + (_target != null ? _target.hashCode() : 0);
231             return result;
232         }
233 
234         public boolean isRoot()
235         {
236             return this._root;
237         }
238     }
239     
240     
241     public TemplateManager getCompositeComponentClient()
242     {
243         return _compositeComponentClient;
244     }
245 
246     public void setCompositeComponentClient(
247             TemplateManager compositeComponentClient)
248     {
249         _compositeComponentClient = compositeComponentClient;
250     }
251 
252     
253     @Override
254     public ValueExpression getParameter(String key)
255     {
256         TemplateManagerImpl client;
257         Iterator<TemplateManagerImpl> itr = _clients.iterator();
258         while (itr.hasNext())
259         {
260             client = itr.next();
261             if (!client.isParamentersMapEmpty() &&
262                  client.getParametersMap().containsKey(key))
263             {
264                 return client.getParametersMap().get(key);
265             }
266         }
267         return null;
268     }
269 
270     @Override
271     public void setParameter(String key, ValueExpression value)
272     {
273         if (_lastClient != null)
274         {
275             _lastClient.getParametersMap().put(key, value);
276         }
277     }
278 
279     @Override
280     public boolean isParameterEmpty()
281     {
282         TemplateManagerImpl client;
283         Iterator<TemplateManagerImpl> itr = _clients.iterator();
284         while (itr.hasNext())
285         {
286             client = itr.next();
287             if (!client.isParamentersMapEmpty())
288             {
289                 return false;
290             }
291         }
292         return true;
293     }
294     
295     public Map<String, ValueExpression> getParameterMap()
296     {
297         return new TemplateClientAttributeMap();
298     }
299 
300     private final class TemplateClientAttributeMap extends AbstractAttributeMap<ValueExpression>
301     {
302 
303         public TemplateClientAttributeMap()
304         {
305         }
306         
307         @Override
308         protected ValueExpression getAttribute(String key)
309         {
310             TemplateManagerImpl client;
311             Iterator<TemplateManagerImpl> itr = _clients.iterator();
312             while (itr.hasNext())
313             {
314                 client = itr.next();
315                 if (!client.isParamentersMapEmpty() &&
316                      client.getParametersMap().containsKey(key))
317                 {
318                     return client.getParametersMap().get(key);
319                 }
320             }
321             return null;
322         }
323 
324         @Override
325         protected void setAttribute(String key, ValueExpression value)
326         {
327             if (_lastClient != null)
328             {
329                 _lastClient.getParametersMap().put(key, value);
330             }
331         }
332 
333         @Override
334         protected void removeAttribute(String key)
335         {
336             if (_lastClient != null)
337             {
338                 _lastClient.getParametersMap().remove(key);
339             }
340         }
341 
342         @Override
343         protected Enumeration<String> getAttributeNames()
344         {
345             Set<String> attributeNames = new HashSet<String>();
346             TemplateManagerImpl client;
347             Iterator<TemplateManagerImpl> itr = _clients.iterator();
348             while (itr.hasNext())
349             {
350                 client = itr.next();
351                 if (!client.isParamentersMapEmpty())
352                 {
353                     attributeNames.addAll(client.getParametersMap().keySet());
354                 }
355             }
356             
357             return new ParameterNameEnumeration(attributeNames.toArray(new String[attributeNames.size()]));
358         }
359     }
360     
361     private static class ParameterNameEnumeration implements Enumeration<String>
362     {
363         private final String[] _parameterNames;
364         private final int _length;
365         private int _index;
366 
367         public ParameterNameEnumeration(final String[] parameterNames)
368         {
369             _parameterNames = parameterNames;
370             _length = parameterNames.length;
371         }
372 
373         public boolean hasMoreElements()
374         {
375             return _index < _length;
376         }
377 
378         public String nextElement()
379         {
380             if (!hasMoreElements())
381             {
382                 throw new NoSuchElementException();
383             }
384             return _parameterNames[_index++];
385         }
386     }
387     
388     /**
389      * This is just a dummy template client that does nothing that is added by default
390      * for each template context 
391      *
392      */
393     public static final class InitialTemplateClient implements TemplateClient
394     {
395         public boolean apply(FaceletContext ctx, UIComponent parent, String name)
396                 throws IOException, FacesException, FaceletException, ELException
397         {
398             return false;
399         }
400     }
401     
402     public static final class InitialPageContext extends PageContext
403     {
404         private boolean _isCacheELExpressions;
405         
406         public InitialPageContext()
407         {
408             _isCacheELExpressions = true;
409         }
410         
411         @Override
412         public Map<String, ValueExpression> getAttributes()
413         {
414             return Collections.emptyMap();
415         }
416 
417         @Override
418         public int getAttributeCount()
419         {
420             return 0;
421         }
422 
423         @Override
424         public boolean isAllowCacheELExpressions()
425         {
426             return _isCacheELExpressions;
427         }
428 
429         @Override
430         public void setAllowCacheELExpressions(boolean cacheELExpressions)
431         {
432             _isCacheELExpressions = cacheELExpressions;
433         }
434     }
435 
436 
437     @Override
438     public boolean isAllowCacheELExpressions()
439     {
440         return _isCacheELExpressions;
441     }
442 
443     @Override
444     public void setAllowCacheELExpressions(boolean cacheELExpressions)
445     {
446         _isCacheELExpressions = cacheELExpressions;
447     }
448     
449     
450 }